1 回答

TA貢獻1880條經驗 獲得超4個贊
問題在于漸變填充樣式實際應用于甜甜圈的方式。你和我最初的假設是,chart.js 將負責定位漸變并將其縮放到適當的大小以填充甜甜圈。嗯,事實并非如此。相反,它使用畫布上漸變的大小和位置。
為了更好地理解,讓我們看一下其中一個漸變的代碼:
const red = "hsla(1, 73.7%, 38.8%, 1)"
const gradient = ctx.createRadialGradient(100,100,31, 100,100,70);
const innerColor = "hsla(1, 60%, 30%, 1)"
const mainColor = red
const outerColor = "hsla(1, 73.7%, 48%, 1)"
gradient.addColorStop(0, innerColor);
gradient.addColorStop(.04, innerColor);
gradient.addColorStop(.05, mainColor);
gradient.addColorStop(1, outerColor);
這將在 x=100 和 y=100 處產生直徑為 140 像素的漸變,如下所示:
現在,如果我們進一步挖掘并假設您繪制的實際畫布的大小是 797 x 419 像素,我們可以看到問題:
漸變完全脫離了甜甜圈的形狀!
為了解決這個問題,漸變需要位于甜甜圈的中心,并且具有適當的大小以完全填充它。有點像這樣:
這說起來容易做起來難,因為最初我們不知道畫布的確切大小,因為 Chart.js 會自動拉伸它以填充瀏覽器窗口。
因此,我們可以采取以下解決方法:
使用 Chart.js 創建甜甜圈,但先不要填充它
等到 Chart.js 觸發調整大小事件以獲取畫布的實際大小
根據畫布的大小計算漸變的尺寸并將其繪制在中心
最后用漸變填充甜甜圈的背景顏色
這是一個示例(請以“全頁”運行,因為我們在 stackoverflow 的迷你預覽框架中沒有獲得正確的窗口大?。?/p>
const canvas = document.querySelector('.d-goal--canvas');
const ctx = canvas.getContext('2d')
const red = "hsla(1, 73.7%, 38.8%, 1)"
let gradient1;
let gradient2;
function createGradient1(ctx) {
const gradient = ctx.createRadialGradient(canvas.width / 2, canvas.height / 2, canvas.height / 4, canvas.width / 2, canvas.height / 2, canvas.height / 2);
const innerColor = "hsla(1, 60%, 30%, 1)"
const mainColor = red
const outerColor = "hsla(1, 73.7%, 48%, 1)"
gradient.addColorStop(0, innerColor);
gradient.addColorStop(.12, innerColor);
gradient.addColorStop(.121, mainColor);
gradient.addColorStop(1, outerColor);
return gradient;
}
function createGradient2(ctx) {
const gradient = ctx.createRadialGradient(canvas.width / 2, canvas.height / 2, canvas.height / 4, canvas.width / 2, canvas.height / 2, canvas.height / 2);
const innerColor = "hsla(1, 90%, 10%, 1)"
const mainColor = "hsla(1, 73.7%, 20%, 1)"
const outerColor = "transparent"
gradient.addColorStop(0, innerColor);
gradient.addColorStop(.12, innerColor);
gradient.addColorStop(.121, mainColor);
gradient.addColorStop(.99, mainColor);
gradient.addColorStop(1, outerColor);
return gradient;
}
function resized() {
gradient1 = createGradient1(ctx);
gradient2 = createGradient2(ctx);
config.data.datasets[0].backgroundColor = [gradient1, gradient2];
donut.update();
}
var config = {
type: 'doughnut',
data: {
labels: [
"Pledged",
"Missing"
],
datasets: [{
label: "Donations",
data: [420, 80],
cubicInterpolationMode: "monotone"
}]
},
options: {
onResize: resized,
legend: {
display: false
}
}
};
const donut = new Chart(ctx, config);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<canvas class="d-goal--canvas"></canvas>
添加回答
舉報