Aadam
Aadam

Reputation: 1541

chartjs gradient with angle

I have been trying different ways to achieve

linear-gradient(135deg, #FBCF33 0%, #F53939 90%);

in my bar chart. I got close to the required gradient. However, failed to achieve exactly the same as the one in CSS.

As far as I understand this is due to the angle. How to achieve the same with createLinearGradient

below is what I tried.

const angle = 136 * Math.PI / 180;
var x2 = 400 * Math.cos(angle);  // angle in radians
var y2 = 400 * Math.sin(angle);  // angle in radians
var g1 = ctx.createLinearGradient(0, 0, x2, y2);
    g1.addColorStop(0, '#EDDE5D');   
    g1.addColorStop(0.5, '#F09819');

Can someone share some thoughts on this?

EDIT:

Dataset with color

const equipment = [100, 0, 20, 10, 60, 20, 0, 0, 20];
function bgColor(context, c1, c2) {
    const {chart, datasetIndex, index} = context;
    const ds = chart.data.datasets[datasetIndex];
    const value = ds.data[index];
    const y = chart.scales.y.getPixelForValue(value);
    const meta = chart.getDatasetMeta(datasetIndex);
    const data = meta.data[index];
    const {x, width, base} = data;
    if (x) {
      const ctx = chart.ctx;
      const gradient = ctx.createLinearGradient(x, y, x + width, base);
      gradient.addColorStop(0, c1);
      gradient.addColorStop(0.9, c2);
      return gradient;
    }
}

datasets: [
        {
            label: 'Equipment',
            data: equipment,
            backgroundColor(context) {
                return bgColor(context, '#EDDE5D', '#F09819');
            },
            tension: 0.4,
            fill: false,
            borderWidth: 0,
            hoverBorderColor: "#000",
            hoverBackgroundColor: '#FBCF33',
            hoverBorderWidth: 1,
        }]

Upvotes: 1

Views: 497

Answers (1)

Luke Trenaman
Luke Trenaman

Reputation: 383

You are correct in identifying the issue as the angle! Your issue here is that the way CSS linear-gradient interprets "angle".

For CSS:

The gradient line's angle of direction. A value of 0deg is equivalent to to top; increasing values rotate clockwise from there.

Visualization of the angles:

enter image description here

When working with Javascript canvas, however, your origin lies with positive x to the right and positive y to the bottom, creating something that looks like this:

enter image description here

This is causing your gradient to actually be set up in a location off the canvas! Accounting for this, you can match the gradient by setting the same color stops as your CSS code, but adjusting the angle to be 45 degrees. Here's a working example of this:

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const angle = 45 * Math.PI / 180;
var x2 = 400 * Math.cos(angle);  // angle in radians
var y2 = 400 * Math.sin(angle);  // angle in radians
var g1 = ctx.createLinearGradient(0, 0, x2, y2);
    g1.addColorStop(0, '#FBCF33');   
    g1.addColorStop(0.9, '#F53939');
    ctx.fillStyle = g1;
    ctx.fillRect(0, 0, 400, 400);
div{
   width:400px;
   height:400px; 
   background: linear-gradient(135deg, #FBCF33 0%, #F53939 90%);
}
<!DOCTYPE html>
<html>
    <head>
        <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
        <link type="text/css" rel="stylesheet" href="stylesheet.css"/>
    </head>
    <body>
        <div></div>
        <canvas id="canvas" width="400" height="400"></canvas>
        <script src="index.js"></script>
    </body>
</html>

Upvotes: 1

Related Questions