Javascript 如何在Chart.js';什么是甜甜圈图?

Javascript 如何在Chart.js';什么是甜甜圈图?,javascript,dom,html5-canvas,chart.js,Javascript,Dom,Html5 Canvas,Chart.js,我正在尝试创建两个径向渐变,以便与 渐变应该看起来有点像下面的图像,但是是红色的。 使用vanilla javascript和DOM创建渐变(createRadialGradient)非常简单,如下代码片段所示: “严格使用” 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%,4

我正在尝试创建两个径向渐变,以便与

渐变应该看起来有点像下面的图像,但是是红色的。

使用vanilla javascript和DOM创建渐变(
createRadialGradient
)非常简单,如下代码片段所示:

“严格使用”
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.queryselectoral('canvas.vanilla')
var{ctx,gradient}=createGradient1(画布列表[0]。getContext('2d'))
ctx.fillStyle=渐变
drawRect(ctx)
var{ctx,gradient}=createGradient1(画布列表[1]。getContext('2d'))
ctx.strokeStyle=梯度
ctx.lineWidth=42
牵引弧(ctx)
var{ctx,gradient}=createGradient2(画布列表[2]。getContext('2d'))
ctx.fillStyle=渐变
drawRect(ctx)
var{ctx,gradient}=createGradient2(画布列表[3]。getContext('2d'))
ctx.strokeStyle=梯度
ctx.lineWidth=42
牵引弧(ctx)
函数createGradient1(ctx){
//内圈在x=110,y=90,半径为30
//外圈在x=100,y=100,半径为70
//ctx.createRadialGradient(x0,y0,r0,x1,y1,r1)
常数梯度=ctx.createRadialGradient(100100,31,100100,70);
//添加三个颜色停止
const innerColor=redDark
常量mainColor=红色
常量外颜色=红灯
gradient.addColorStop(0,innerColor);
渐变.addColorStop(.04,innerColor);
渐变。添加颜色停止(.05,主颜色);
渐变。添加颜色停止(1,外部颜色);
返回{ctx,gradient}
}
函数createGradient2(ctx){
//内圈在x=110,y=90,半径为30
//外圈在x=100,y=100,半径为70
//ctx.createRadialGradient(x0,y0,r0,x1,y1,r1)
常数梯度=ctx.createRadialGradient(100100,31,100100,70);
//添加三个颜色停止
const innerColor=“hsla(1,90%,10%,1)”
const mainColor=“hsla(1,73.7%,20%,1)”
const outerColor=“透明”
gradient.addColorStop(0,innerColor);
渐变.addColorStop(.04,innerColor);
渐变。添加颜色停止(.05,主颜色);
gradient.addColorStop(.7,主色);
渐变色.addColorStop(.73,外层颜色);
返回{ctx,gradient}
}
函数drawRect(ctx){
//ctx.fillRect(x,y,宽度,高度)
ctx.fillRect(20,20,160,160);
}
函数drawArc(ctx){
ctx.beginPath();
//ctx.弧(x,y,半径,星形,端角[,逆时针])
ctx.arc(100,100,50,0,2*Math.PI);
ctx.stroke()
}
.vanilla{
显示:内联块;
}

问题在于渐变填充样式实际应用于甜甜圈的方式。您(也是我最初的)假设是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)”
设梯度1;
设梯度2;
函数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)”
常量mainColor=红色
const outerColor=“hsla(1,73.7%,48%,1)”
gradient.addColorStop(0,innerColor);
渐变.addColorStop(.12,innerColor);
渐变色.addColorStop(.121,主色);
渐变。添加颜色停止(1,外部颜色);
回归梯度;
}
函数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=“透明”
gradient.addColorStop(0,innerColor);
渐变.addColorStop(.12,innerColor);
渐变色.addColorStop(.121,主色);
渐变色.addColorStop(.99,主色);
渐变。添加颜色停止(1,外部颜色);
回归梯度;
}
函数大小调整(){
gradient1=createGradient1(ctx);
gradient2=createGradient2(ctx);
config.data.datasets[0].backgroundColor=[gradient1,gradient2];
update();
}
变量配置={
键入:“甜甜圈”,
数据:{
标签:[
“承诺”,
“失踪”
],
数据集:[{
标签:“捐赠”,
数据:[420,80],
库宾特波拉蒂