我正在尝试创建两个径向渐变以与Charts.js甜甜圈图一起使用。
createRadialGradient
使用香草javascript和DOM创建渐变()非常简单,如下面的代码片段所示:
'use strict'
const red = "hsla(1, 73.7%, 38.8%, 1)"
const redDark = "hsla(1, 60%, 30%, 1)"
const redDarker = "hsla(1, 20%, 20%, 1)"
const redLight = "hsla(1, 73.7%, 48%, 1)"
const canvasList = document.querySelectorAll('canvas.vanilla')
var {ctx, gradient} = createGradient1(canvasList[0].getContext('2d'))
ctx.fillStyle = gradient
drawRect(ctx)
var {ctx, gradient} = createGradient1(canvasList[1].getContext('2d'))
ctx.strokeStyle = gradient
ctx.lineWidth = 42
drawArc(ctx)
var {ctx, gradient} = createGradient2(canvasList[2].getContext('2d'))
ctx.fillStyle = gradient
drawRect(ctx)
var {ctx, gradient} = createGradient2(canvasList[3].getContext('2d'))
ctx.strokeStyle = gradient
ctx.lineWidth = 42
drawArc(ctx)
function createGradient1 (ctx) {
// The inner circle is at x=110, y=90, with radius=30
// The outer circle is at x=100, y=100, with radius=70
// ctx.createRadialGradient(x0, y0, r0, x1, y1, r1)
const gradient = ctx.createRadialGradient(100,100,31, 100,100,70);
// Add three color stops
const innerColor = redDark
const mainColor = red
const outerColor = redLight
gradient.addColorStop(0, innerColor);
gradient.addColorStop(.04, innerColor);
gradient.addColorStop(.05, mainColor);
gradient.addColorStop(1, outerColor);
return { ctx, gradient }
}
function createGradient2 (ctx) {
// The inner circle is at x=110, y=90, with radius=30
// The outer circle is at x=100, y=100, with radius=70
// ctx.createRadialGradient(x0, y0, r0, x1, y1, r1)
const gradient = ctx.createRadialGradient(100,100,31, 100,100,70);
// Add three color stops
const innerColor = "hsla(1, 90%, 10%, 1)"
const mainColor = "hsla(1, 73.7%, 20%, 1)"
const outerColor = "transparent"
gradient.addColorStop(0, innerColor);
gradient.addColorStop(.04, innerColor);
gradient.addColorStop(.05, mainColor);
gradient.addColorStop(.7, mainColor);
gradient.addColorStop(.73, outerColor);
return { ctx, gradient }
}
function drawRect (ctx) {
// ctx.fillRect(x, y, width, height)
ctx.fillRect(20, 20, 160, 160);
}
function drawArc (ctx) {
ctx.beginPath();
// ctx.arc(x, y, radius, startAngle, endAngle [, anticlockwise])
ctx.arc(100, 100, 50, 0, 2 * Math.PI);
ctx.stroke()
}
.vanilla {
display: inline-block;
}
<canvas class="vanilla" width="180" height="180"></canvas>
<canvas class="vanilla" width="180" height="180"></canvas>
<canvas class="vanilla" width="180" height="180"></canvas>
<canvas class="vanilla" width="180" height="180"></canvas>
但是,当我对Charts.js应用相同的2个渐变时,会得到灰色的甜甜圈。使用单个渐变不会更改结果。但是,使用两种Hsla颜色可以正常工作(red
&"white"
)。
/** @type {CanvasRenderingContext2D} */
const ctx = document.querySelector('.d-goal--canvas').getContext('2d')
const red = "hsla(1, 73.7%, 38.8%, 1)"
const { gradient1 } = createGradient1(ctx)
const { gradient2 } = createGradient2(ctx)
const donut = new Chart(ctx, {
type: 'doughnut',
data: {
labels: [
"Pledged",
"Missing"
],
datasets: [{
label: "Donations",
data: [420, 80],
cubicInterpolationMode: "monotone",
// borderColor: [red, "white"],
// backgroundColor: [red, "white"],
borderColor: [gradient1, gradient2],
backgroundColor: [gradient1, gradient2],
}]
},
options: {
legend: {
display: false
}
}
})
function createGradient1 (ctx) {
// The inner circle is at x=110, y=90, with radius=30
// The outer circle is at x=100, y=100, with radius=70
// ctx.createRadialGradient(x0, y0, r0, x1, y1, r1)
const gradient = ctx.createRadialGradient(100,100,31, 100,100,70);
// Add three color stops
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);
return { ctx, gradient }
}
function createGradient2 (ctx) {
// The inner circle is at x=110, y=90, with radius=30
// The outer circle is at x=100, y=100, with radius=70
// ctx.createRadialGradient(x0, y0, r0, x1, y1, r1)
const gradient = ctx.createRadialGradient(100,100,31, 100,100,70);
// Add three color stops
const innerColor = "hsla(1, 90%, 10%, 1)"
const mainColor = "hsla(1, 73.7%, 20%, 1)"
const outerColor = "transparent"
gradient.addColorStop(0, innerColor);
gradient.addColorStop(.04, innerColor);
gradient.addColorStop(.05, mainColor);
gradient.addColorStop(.7, mainColor);
gradient.addColorStop(.73, outerColor);
return { ctx, gradient }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<canvas class="d-goal--canvas"></canvas>
我究竟做错了什么?
我阅读了Jelena Jovanovic的渐变教程,该教程是createLinearGradient
应用于折线图的线性渐变(),我看不出自己在做什么。据我所知,也许我的渐变区域是错误的,但不应导致显示灰色图表。
Charts.js文档中有一个有关颜色的部分,其中描述了如何使用颜色,CanvasGradient
但仅用于createLinearGradient
,这使我认为这可能是Charts.js中的错误...
问题是渐变填充样式实际应用于甜甜圈的方式。您(也是我最初的假设)是,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像素,我们可以看到问题所在:
渐变完全超出了甜甜圈的形状!
To fix it, the gradient would need to be in the center of the doughnut and have the appropriate size to fill it entirely. A little something like this:
Well this is easier said then done because initially we don't know the exact size of the canvas as chart.js automatically stretches it to fill the browser window.
So what we can do to workaround goes a little something like this:
这是一个示例(请以“整页”运行,因为我们在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>
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句