最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - ChartJS Doughnut Charts Gradient Fill - Stack Overflow

programmeradmin3浏览0评论

So I tried to make a gradient fill for the ChartJS doughnut chart, but this only works horizontal and not in a circle.

This is the code that I'm using:

   var ctx = document.getElementById("chart-area").getContext("2d");

   var gradient1 = ctx.createLinearGradient(0, 0, 0, 175);
   gradient1.addColorStop(0.0, '#ACE1DB');
   gradient1.addColorStop(1.0, '#7FBDB9');


   var gradient2 = ctx.createLinearGradient(0, 0, 400, 400);
   gradient2.addColorStop(0, '#B5D57B');
   gradient2.addColorStop(1, '#98AF6E');

   var gradient3 = ctx.createLinearGradient(0, 0, 0, 175);
   gradient3.addColorStop(0, '#E36392');
   gradient3.addColorStop(1, '#FE92BD');

   var gradient4 = ctx.createLinearGradient(0, 0, 0, 175);
   gradient4.addColorStop(1, '#FAD35E');
   gradient4.addColorStop(0, '#F4AD4F');

   /* ADD DATA TO THE DOUGHNUT CHART */
   var doughnutData = [
    {
      value: 80,
      color: gradient1,
      highlight: "#E6E6E6",
      label: "NUTRIENTS"
    },
    {
      value: 20,
      color:"#E6F1EE"

    },
    {
      value:50,
      color: gradient2,
      highlight: "#E6E6E6",
      label: "PROTEINE"
    },
    {
      value: 50,
      color:"#E6F1EE"
    },
    {
      value: 75,
      color: gradient3,
      highlight: "#E6E6E6",
      label: "FETTE"
    },
    {
      value:25,
      color:"#E6F1EE"
    },
    {
      value: 77,
      color: gradient4,
      highlight: "#E6E6E6",
      label: "CARBS"
    }
    {
      value: 23,
      color:"#E6F1EE"
    },
   ];

Is it possible to implement the gradient on a radius, as seen on this design?

Thanks!

So I tried to make a gradient fill for the ChartJS doughnut chart, but this only works horizontal and not in a circle.

This is the code that I'm using:

   var ctx = document.getElementById("chart-area").getContext("2d");

   var gradient1 = ctx.createLinearGradient(0, 0, 0, 175);
   gradient1.addColorStop(0.0, '#ACE1DB');
   gradient1.addColorStop(1.0, '#7FBDB9');


   var gradient2 = ctx.createLinearGradient(0, 0, 400, 400);
   gradient2.addColorStop(0, '#B5D57B');
   gradient2.addColorStop(1, '#98AF6E');

   var gradient3 = ctx.createLinearGradient(0, 0, 0, 175);
   gradient3.addColorStop(0, '#E36392');
   gradient3.addColorStop(1, '#FE92BD');

   var gradient4 = ctx.createLinearGradient(0, 0, 0, 175);
   gradient4.addColorStop(1, '#FAD35E');
   gradient4.addColorStop(0, '#F4AD4F');

   /* ADD DATA TO THE DOUGHNUT CHART */
   var doughnutData = [
    {
      value: 80,
      color: gradient1,
      highlight: "#E6E6E6",
      label: "NUTRIENTS"
    },
    {
      value: 20,
      color:"#E6F1EE"

    },
    {
      value:50,
      color: gradient2,
      highlight: "#E6E6E6",
      label: "PROTEINE"
    },
    {
      value: 50,
      color:"#E6F1EE"
    },
    {
      value: 75,
      color: gradient3,
      highlight: "#E6E6E6",
      label: "FETTE"
    },
    {
      value:25,
      color:"#E6F1EE"
    },
    {
      value: 77,
      color: gradient4,
      highlight: "#E6E6E6",
      label: "CARBS"
    }
    {
      value: 23,
      color:"#E6F1EE"
    },
   ];

Is it possible to implement the gradient on a radius, as seen on this design?

Thanks!

Share Improve this question edited May 14, 2015 at 9:39 user1693593 asked May 12, 2015 at 9:11 T.B.T.B. 1131 gold badge1 silver badge5 bronze badges 2
  • This workaround works, it fills a gradient, but the problem is the angle of the gradient, because it is a circle! – T.B. Commented May 13, 2015 at 9:17
  • I've posted an answer with a couple of possible options to create you gradient donut chart. – markE Commented May 13, 2015 at 15:57
Add a comment  | 

3 Answers 3

Reset to default 11

ChartJS will not (properly) use gradient fill colors when drawing a linear gradient on non-linear paths like your donut chart. A linear gradient does not curve.

Possibility #1 -- use a radial gradient

You might experiment with a radial gradient and see if the results meets your design needs.

Possibility #2 -- use a gradient stroke (a DIY project)

Also, canvas's stroke will curve around a circle.

If you want to "roll-your-own" gradient donut chart, here's example code and a Demo that uses a gradient strokeStyle on a circular path (see my previous answer here: Angle gradient in canvas):

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");

function drawMultiRadiantCircle(xc, yc, r, radientColors) {
  var partLength = (2 * Math.PI) / radientColors.length;
  var start = 0;
  var gradient = null;
  var startColor = null,
      endColor = null;

  for (var i = 0; i < radientColors.length; i++) {
    startColor = radientColors[i];
    endColor = radientColors[(i + 1) % radientColors.length];

    // x start / end of the next arc to draw
    var xStart = xc + Math.cos(start) * r;
    var xEnd = xc + Math.cos(start + partLength) * r;
    // y start / end of the next arc to draw
    var yStart = yc + Math.sin(start) * r;
    var yEnd = yc + Math.sin(start + partLength) * r;

    ctx.beginPath();

    gradient = ctx.createLinearGradient(xStart, yStart, xEnd, yEnd);
    gradient.addColorStop(0, startColor);
    gradient.addColorStop(1.0, endColor);

    ctx.strokeStyle = gradient;
    ctx.arc(xc, yc, r, start, start + partLength);
    ctx.lineWidth = 30;
    ctx.stroke();
    ctx.closePath();

    start += partLength;
  }
}

var someColors = [];
someColors.push('#0F0');
someColors.push('#0FF');
someColors.push('#F00');
someColors.push('#FF0');
someColors.push('#F0F');

drawMultiRadiantCircle(150, 150, 120, someColors);
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=300 height=300></canvas>

yes What I did on my end is this.

Step 1 - Grab your chart.

  @ViewChild('slideDoughnutChart') slideDoughnutChart: BaseChartDirective;

Step 2 - Declare a const gradient and assign it.

const gradient = this.slideDoughnutChart.chart.ctx.createLinearGradient(0, 0, 0, 220);

Step 3 - Push the colors that you wan to see as Gradient.

const colors = [];
for (let i = 0; i < 4; i++) {
  gradient.addColorStop(0, 'rgb(37, 77, 180)');
  gradient.addColorStop(1, 'rgb(123, 98, 221)');
  colors.push(gradient);
}

Here I have pushed the same color.

Step 4 - Set doughnut chart colors variable to colors array.

this.slideDoughnutChartColors = [{ backgroundColor: colors }];

Step 5 - Assign slideDoughnutChartColors variable to colors binding in canvas.

<canvas class="chartjs canvasResponsive" baseChart #slideDoughnutChart="base-chart" [colors]="slideDoughnutChartColors" ></canvas>

If you follow the steps correctly, You will end with this.

For 4 different colors you need to create 4 different variables. For example something like this.

const gradientOne = this.slideDoughnutChart.chart.ctx.createLinearGradient(0, 0, 0, 400);
const gradientTwo = this.slideDoughnutChart.chart.ctx.createLinearGradient(0, 0, 100, 400);
const gradientThree = this.slideDoughnutChart.chart.ctx.createLinearGradient(0, 0, 0, 400);
const gradientFour = this.slideDoughnutChart.chart.ctx.createLinearGradient(0, 0, 0, 400);

then doing something like this.

 for (let i = 0; i < this.slideDoughnutChartData.length; i++) {
      switch (i) {
        case 0:
          gradientOne.addColorStop(0, 'rgb(223, 43, 100)');
          gradientOne.addColorStop(1, 'rgb(224, 105, 84)');
          colors.push(gradientOne);
          break;
        case 1:
          gradientTwo.addColorStop(0, 'rgb(248, 188, 80)');
          gradientTwo.addColorStop(1, 'rgb(243, 217, 53)');
          colors.push(gradientTwo);
          break;
        case 2:
          gradientThree.addColorStop(0, 'rgb(147, 229, 151)');
          gradientThree.addColorStop(1, 'rgb(3, 220, 179)');
          colors.push(gradientThree);
          break;
        case 3:
          gradientFour.addColorStop(0, 'rgb(123, 98, 221)');
          gradientFour.addColorStop(1, 'rgb(37, 77, 180)');
          colors.push(gradientFour);
          break;
      }
    }

will end you up with.

This is my data for the chart.

this.slideDoughnutChartData = [25, 35, 20, 25, 2];

2023 Answer:

I know this question has been asked long ago and have been answered, but I thought it would be beneficial for anyone looking for an updated answer to know that in addition to the standard built-in linear and radial gradients, there is now a third - conical gradient - that does exactly what we're looking for.

Here's the link to the docs.

And a simple example of how it's implemented to achieve the effect in a Chartjs doughnut chart:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Doughnut Chart Example</title>
  <!-- Include Chart.js library -->
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
    <div style="width: 400px; height: 400px;">
      <canvas id="myDoughnutChart" width="400" height="400"></canvas>
    </div>

  <script>
    // Data for the doughnut chart
    const chartRef = document.getElementById('myDoughnutChart');
    
    let gradient = chartRef.getContext('2d').createConicGradient(0, 200, 200);

    gradient.addColorStop(0, "red");
    gradient.addColorStop(0.25, "orange");
    gradient.addColorStop(0.5, "yellow");
    gradient.addColorStop(0.75, "green");
    gradient.addColorStop(1, "blue");
    
    const data = {
      labels: ['Red-Orange', 'Orange-Yellow', 'Yellow-Green'],
      datasets: [{
        label: 'My Doughnut Chart',
        data: [30, 20, 50],
        backgroundColor: gradient,
        hoverOffset: 4
      }]
    };

    // Configuration for the doughnut chart
    const config = {
      type: 'doughnut',
      data: data,
    };

    // Create the chart
    const myDoughnutChart = new Chart(
      chartRef,
      config
    );
  </script>
</body>
</html>

The above implementation of the gradient to the chart is simply to display its effect. Ideally, the gradient should be applied to each segment separately, but this would require calculating each segment's starting angle.

Hope it helps!

发布评论

评论列表(0)

  1. 暂无评论