The finished effect is as follows:

First, draw a static pie chart

Step1 set the coordinates of the center of the circle and draw large and small circles with radius

<canvas id="myCanvas" width="600" height="600"></canvas>
Copy the code

css

canvas {
    border: 1px solid #ccc;
}
Copy the code

js

var canvas = document.getElementById("myCanvas");
var context = canvas.getContext('2d'); var cX = canvas.width / 2; Var cY = canvas. Height / 2; Var bR = 200; Var sR = 100; // set the radius of the small circle // step1 create a large circle context.beginpath (); context.arc(cX, cY, bR, 0, 2 * Math.PI); context.fillStyle ='red'; context.fill(); // step2 create a small circle context.beginpath (); context.arc(cX, cY, sR, 0, 2 * Math.PI); context.fillStyle ='white';
context.fill();
Copy the code

Step2 draw 45° sector

// step1 create a large circle context.beginpath (); context.moveTo(cX, cY); context.lineTo(cX + bR, cY); context.arc(cX, cY, bR, 0, 1 / 8 * 2 * Math.PI); // Draw a 45° circle context.lineTo(cX, cY); context.fillStyle ='red'; context.fill(); // step2 create a small circle context.beginpath (); context.moveTo(cX, cY); context.lineTo(cX + sR, cY); context.arc(cX, cY, sR, 0, 1 / 8 * 2 * Math.PI); // Draw a 45° circle context.lineTo(cX, cY); context.fillStyle ='white';
context.fill();
Copy the code

There is a problem (JS decimal point problem) in the above code, as shown below, the small circle does not fill the large circle completely, and there is a red dotted line at the edge

context.strokeStyle = "white";
context.stroke();
context.lineWidth = 2;
Copy the code

Step3 encapsulates the codes of large circles and small circles to facilitate the creation of multiple sectors with different radians

functionDrawDonuts (startAngle, endAngle, color) {// step1 create a large circle context.beginpath (); context.moveTo(cX, cY); context.lineTo(cX + bR * Math.cos(startAngle), cY + bR * Math.sin(startAngle)); context.arc(cX, cY, bR, startAngle, endAngle); context.lineTo(cX, cY); context.fillStyle = color; context.fill(); // step2 create a small circle context.beginpath (); context.moveTo(cX, cY); context.lineTo(cX + sR * Math.cos(startAngle), cY + sR * Math.sin(startAngle)); context.arc(cX, cY, sR, startAngle, endAngle); context.lineTo(cX, cY); context.fillStyle ='pink'; context.fill(); // Add the following code to solve the problem that the smaller circle does not fill the larger circle completely, as shown in the image above, there is a red dotted line around the edge context.strokestyle ="pink";
    context.stroke();
    context.lineWidth = 2;

    }
Copy the code
// Set the radian ratio for each sector and the color varsetArr = [{scale: 0.2 * 2 * Math.PI, color:"red"}, {scale: 0.35 * 2 * math.pi, color:"cyan"}, {scale: 0.25 * 2 * math.pi, color:"purple"}, {scale: 0.1 * 2 * math.pi, color:"blue"}, {scale: 0.1 * 2 * math.pi, color:"orange"
}];

var startAngle = 0;
var endAngle = 0;
for(var i =0; i<setArr.length; i++){ endAngle +=setArr[i].scale;
    drawDonuts(startAngle,endAngle,setArr[i].color); // call the wrapper function startAngle = endAngle; }Copy the code

Second, dynamic implementation

Step1 to achieve solid-color donut animation display

Comment this code //for(var i =0; i<setArr.length; i++){ // endAngle +=setArr[i].scale;
//     drawDonuts(startAngle,endAngle,setArr[i].color); // startAngle = endAngle; // } var speed = 5 / 360 * 2 * Math.PI; Var timer1 = control the speed of dynamic displaysetInterval(function() {
    if(endAngle > 2 * Math.PI) { clearInterval(timer1); } endAngle += speed; drawDonuts(startAngle, endAngle,'cyan'); startAngle = endAngle; }, 1000/40);Copy the code

Step2 realize the dynamic effect display of donuts with different colors

var speed = 5 / 360 * 2 * Math.PI; Var dataArr = [0]; var sum = 0;for (var i = 0; i < setArr.length; i++) {
    sum += setArr[i].scale;
    dataArr.push(sum);
}
var timer1 = setInterval(function() {
    endAngle += speed;
    if(endAngle > 2 * Math.PI) { clearInterval(timer1); // Optimize performance, do not continue rendering}for (var i = 1; i < dataArr.length; i++) {
        if (endAngle >= dataArr[i - 1] && endAngle <= dataArr[i]){
            drawDonuts(startAngle, endAngle, setArr[i - 1].color);
            break; }} startAngle = endangle-0.01; // Handle the gap problem in dynamic effect rotation}, 1000/40);Copy the code

Game over — ending

Too little writing articles, expression is not good, welcome everyone to offer valuable opinions ~ grateful ~