canvas 饼图 - 算法 - 错误结果

pie chart with canvas - algorithm - wrong result

我写了这个算法,它基于数组中的数据,使用 canvas 元素制作饼图:

        function pieChart() {
            canvas = document.getElementById('pie-chart');
            canvas.width = 300;
            canvas.height = 300;
            context = canvas.getContext('2d');

            const data = [1, 5, 4, 3];
            const colors = ['brown', 'yellow', 'purple', 'pink'];

            let summ = 0;
            for (let index = 0; index < data.length; index++) {
                summ += data[index];
            }

            function deg(num) {
                return num / summ * 360;
            }

            function rad(deg) {
                return deg * (Math.PI / 180);
            }

            let start = 3 * Math.PI / 2;

            for (let index = 0; index < data.length; index++) {
                context.beginPath();
                context.moveTo(150, 150);
                context.arc(150, 150, 150, start, rad(deg(data[index])), false);
                context.lineTo(150, 150);
                context.fillStyle = colors[index];
                context.fill();
                start = rad(deg(data[index]));
            }
        }
<body onload="pieChart();">
    <canvas id="pie-chart"></canvas>
</body>

这是我得到的结果:

我做错了什么?

有两个值得注意的问题。

  1. start = rad(deg(data[index]));

您正在将起始角度移动到恰好是前一个楔形的大小,而实际上,您想要添加前一个楔形的大小。这应该是:

start += rad(deg(data[index]));
  1. context.arc(150, 150, 150, start, rad(deg(data[index])), false);

您在此处指定的结束角度是楔角的大小。它需要从起始角​​度偏移(即您必须向其添加起始角度)。这应该是:

context.arc(150, 150, 150, start, start + rad(deg(data[index])), false);

function pieChart() {
  canvas = document.getElementById('pie-chart');
  canvas.width = 300;
  canvas.height = 300;
  context = canvas.getContext('2d');

  const data = [1, 5, 4, 3];
  const colors = ['brown', 'yellow', 'purple', 'pink'];

  let summ = 0;
  for (let index = 0; index < data.length; index++) {
    summ += data[index];
  }

  function deg(num) {
    return num / summ * 360;
  }

  function rad(deg) {
    return deg * (Math.PI / 180);
  }

  let start = 3 * Math.PI / 2;

  for (let index = 0; index < data.length; index++) {
    context.beginPath();
    context.moveTo(150, 150);
    context.arc(150, 150, 150, start, start + rad(deg(data[index])), false);
    context.lineTo(150, 150);
    context.fillStyle = colors[index];
    context.fill();
    start += rad(deg(data[index]));
  }
}
<body onload="pieChart();">
  <canvas id="pie-chart"></canvas>
</body>

您绘制的每条弧线都是从上一条弧线的角度到新弧线的角度,但都从 0 开始。您需要将新弧线的角度添加到之前的结果。

还要注意 arc 函数的最后一个参数。如果为假,则圆弧顺时针绘制,如果为真,则圆弧逆时针绘制。

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arc

 document.addEventListener("DOMContentLoaded", function(){
 
 
            canvas = document.getElementById('pie-chart');
            canvas.width = 300;
            canvas.height = 300;
            context = canvas.getContext('2d');

            const data = [1, 5, 4, 3];
            const colors = ['brown', 'yellow', 'purple', 'pink'];

            let summ = 0;
            for (let index = 0; index < data.length; index++) {
                summ += data[index];
            }

            function deg(num) {
                return (num / summ) * 360;
            }

            function rad(deg) {
                return deg * (Math.PI / 180);
            }


            let lastAngle = 2 * Math.PI; //Starting angle
            let thisAngle = lastAngle;

            for (let index = 0; index < data.length; index++) {
                thisAngle += rad(deg(data[index]));
                context.beginPath();
                context.moveTo(150, 150);
                context.arc(150, 150, 150, lastAngle, thisAngle, false);
                context.lineTo(150, 150);
                context.fillStyle = colors[index];
                context.fill();
                lastAngle = thisAngle;
            }
            
           } );
<html>
<body>
  <canvas id="pie-chart">
  </canvas>
</body>
</html>