I'm trying to create two radial gradients to use with a Charts.js doughnut chart.
The gradients should look kinda like the image below but in red.

Creating the gradients (createRadialGradient) was pretty simple using vanilla javascript and the DOM, as displayed in the code snippet below:
'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>
But when I apply the same 2 gradients to Charts.js, I get a grey doughnut. Using a single gradient does not change the result. However, using two Hsla colors work as expected (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>
What am I doing wrong?
I read Jelena Jovanovic's gradient tutorial, which is a linear gradient (createLinearGradient) applied to a line chart and I do not see what I am doing differently. Perhaps my gradient area is wrong but that should not result in a grey chart, as far as I can tell.
The Charts.js documentation has a section about colors where they describe how to use CanvasGradient but only for createLinearGradient, which makes me think that it might be a bug in Charts.js...


