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 的迷你预览框架中没有获得正确的窗口大小):
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>
添加回答
举报