According to the project requirements, to achieve such a dashboard effect:



Once you get the picture, do a split first, breaking it into several smaller modules. Look from the inside out, first need an inner ring of the scale bar, the inner ring of the scale bar is composed of a number of points, so my way to achieve: first draw a line, through the cycle, rotation to get a circular scale bar

//innerLineNums is the graduated number ctx.save(); for (var i = 0; i <= $this.innerLineNums; i++) { ctx.beginPath(); ctx.lineWidth = 2; CTX. StrokeStyle = 'rgba (155157183, 1); ctx.moveTo(82, 0); ctx.lineTo(80, 0); ctx.stroke(); Rotate (2* math.pi / $this.innerlinenums); rotate(1 * math.pi / $this.innerlinenums); rotate(2* math.pi / $this.innerlinenums); rotate(2* math.pi / $this.innerlinenums); } ctx.restore();Copy the code

Then there are the long scale lines, the number marks, and the text in the middle

Ctx.save (); for (var i = 0; i < 6; i++) { ctx.beginPath(); ctx.lineWidth = 2; CTX. StrokeStyle = 'rgba (155157183, 1); ctx.moveTo(82, 0); ctx.lineTo(78, 0); ctx.stroke(); Rotate (deg1 * 10); rotate(deg1 * 10); rotate(deg1 * 10); } ctx.restore(); // ctx.save(); ctx.rotate(Math.PI / 2); for (i = 0; i < 6; I++) {ctx.fillstyle = 'rgba(165,180,198,.4)'; ctx.font = '10px Microsoft yahei'; ctx.textAlign = 'center'; ctx.fillText(20 * i, 0, -65); ctx.rotate(deg1 * 10); } ctx.restore(); // Inner ring text ctx.save(); ctx.rotate(210 * Math.PI / 180); ctx.fillStyle = '#000'; ctx.font = '44px Microsoft yahei'; ctx.textAlign = 'center'; ctx.textBaseLine = 'top'; ctx.fillText(process, 0, 10); var width = ctx.measureText(process).width; ctx.fillStyle = '#000'; ctx.font = '20px Microsoft yahei'; Ctx. fillText(' ', width / 2 + 10, 10);Copy the code

Now that the inner ring is ready, you can see the following effect:

Then look at the scale bar of the outer ring, there is a gap on the scale bar of the outer ring, visual estimation, calculate the gap is 1/3, that is, the scale line of the outer ring needs to draw 120-360°, the full score here is 100 points, starting from 0, for the convenience of calculation, draw 50 scale lines for him, then the algorithm of the Angle of each scale line deg1 is:

// The calculation formula of arc length is a mathematical formula: L=n (center Angle) × π (1) × r(radius) /180 (Angle), L=α (radian) × r(radius) (radian). Where n is the degree of central Angle, r is the radius, and L is the arc length of central Angle. PI/180 * math.pi /180 * math.pi /180 * math.pi /180 * math.pi /180 * math.pi /180 deg1() { return (Math.PI * 12) / (9 * this.lineNums) }Copy the code

InnerLineNums = 50 * 3/2 = 75 Ok, once you know the Angle, draw a line as you did before, and then loop, rotate, jump and draw a gray outer ring scale:

//lineNums grey long dial number ctx.save(); for (var i = 0; i <= lineNums; i++) { var is_on = (((i - 1) / lineNums) * 100 < activeProcess - 1); var color = getTickColor(is_on, i); ctx.beginPath(); ctx.lineWidth = 2; ctx.strokeStyle = color; ctx.moveTo(radius + 8, 0); ctx.lineTo(radius + 35, 0); ctx.stroke(); Rotate (2* math.pi/innerLineNums); rotate(2* math.pi/innerLineNums); } ctx.restore();Copy the code

At this point it looks like this:

The line is dynamically drawn according to the score, so the length needs to be calculated. I plan to use an arc to achieve this. It says that the rotation arc between each line is deg1, so the length of the arc is equal to Score * deg1/2, and the line is drawn according to the formula as follows:

Var gradient = ctx.createlineargradient (0, 0, $this. ColorLineNums * 2, 0); Gradient. AddColorStop (" 0 ", "rgba (252,,3,44. 6)"); Gradient. AddColorStop (" 0.5 ", "rgba (134,,37,168. 6)"); Gradient. AddColorStop (" 1.0 ", "rgba (54,63,255. 6)"); Ctx.save (); ctx.beginPath(); ctx.lineWidth = 2; ctx.strokeStyle = gradient; ctx.arc(0, 0, radius, 0, angle, false); ctx.stroke(); ctx.restore();Copy the code

It looks like this:

The rotate method uses the radius of the gradient line and the rotate Angle is the corresponding Angle of the current fraction.

/ / the end CTX. The save (); ctx.rotate(activeProcess / 2 * deg1); ctx.beginPath(); ctx.fillStyle = 'rgba(255, 255, 255, 1)'; ctx.arc(radius + 45, 0, 5, 0, Math.PI * 2, false); ctx.fill(); ctx.lineWidth = 1; ctx.strokeStyle = "rgba(246, 5, 51, 1)"; ctx.stroke(); ctx.save(); ctx.beginPath(); ctx.fillStyle = 'rgba(246, 5, 51, 1)'; ctx.arc(radius + 45, 0, 3, 0, Math.PI * 2, false); ctx.fill(); ctx.restore();Copy the code

At this point, also sent a color line, the effect is as follows, the forehead, the color of the line how to do it, do not know how to do first is, after colleagues who give directions, it is concluded that the solution: cut the gradients, how many color thread is divided into many copies, then thank [eat melon seeds gf – color gradient of JS code] [1] to write blog, provides the algorithm

Here’s the final result:

Preview component

It is the first time to write canvas component, and this code is just for reference. Finally, I would like to thank MasqLi-Canvas for imitating Sesame credit sub-dashboard. Only by referring to the codes of the previous two bloggers can I realize the needs of my project. Thanks again to the two bloggers

Color gradient see article

The full demo is here