I want to animate the speedometer using canvas. But it is necessary for me that the speedometer needle be triangular in shape and when the value changes, it shows the required value, but its base always remained in the center. Tell me what formula or algorithm to apply for this. The code is presented just below.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <canvas id="canvas" width="500" height="500"></canvas> <script> const canvas = document.getElementById("canvas"), ctx = canvas.getContext("2d"), // general settings middleX = canvas.width / 2, middleY = canvas.height / 2, radius = 240, counterClockwise = false, // ticks settings tickWidth = canvas.width / 100, // tickColor = "#746845"; tickOffsetFromArc = canvas.width / 40, // Center circle settings centerCircleRadius = canvas.width / 20, centerCircleColor = "#ccc", centerCircleBorderWidth = canvas.width / 100, // Arrow settings arrowValueIndex = .73, arrowColor = "#464646", arrowWidth = canvas.width / 50, // numbers digits = [0, 20, 40, 50, 60, 70, 80, 90, 100], digitsColor = "#0a0a0a", digitsFont = "bold 20px Tahoma", digitsOffsetFromArc = canvas.width / 15, //zones zonesCount = digits.length - 1; // beginning and ending of our arc. Sets by radius*pi let startAngleIndex = .75, endAngleIndex = 2.25, step = (endAngleIndex - startAngleIndex) / zonesCount; /*draw zones*/ let DrawZones = function () { const greyZonesCount = zonesCount / 1.6; greenZonesCount = zonesCount - greyZonesCount, startAngle = (startAngleIndex - 0.02) * Math.PI, endGreyAngle = (startAngleIndex + greyZonesCount * step) * Math.PI, endGreenAngle = (endAngleIndex + 0.02) * Math.PI, //zones' options sectionOptions = [ { startAngle: startAngle, endAngle: endGreyAngle, color: "#e7e7e7", zoneLineWidth: 2 }, { startAngle: endGreyAngle, endAngle: endGreenAngle, color: "#13b74b", zoneLineWidth: 5 }, ]; this.DrawZone = function (options) { ctx.beginPath(); ctx.arc(middleX, middleY, radius, options.startAngle, options.endAngle, counterClockwise); ctx.lineWidth = options.zoneLineWidth; ctx.strokeStyle = options.color; ctx.lineCap = "round"; ctx.stroke(); }; sectionOptions.forEach(options => this.DrawZone(options)); }; /*draw dots*/ let DrawTicks = function () { startAngleIndex = .73, endAngleIndex = 2.27, step = (endAngleIndex - startAngleIndex) / zonesCount; this.DrawTick = function (angle,count) { let fromX = middleX + (radius - tickOffsetFromArc) * Math.cos(angle), fromY = middleY + (radius - tickOffsetFromArc) * Math.sin(angle), toX = middleX + (radius + tickOffsetFromArc) * Math.cos(angle), toY = middleY + (radius + tickOffsetFromArc) * Math.sin(angle), centerOfDotX=(fromX+toX)/2, centerOfDotY=(fromY+toY)/2; ctx.beginPath(); ctx.arc(centerOfDotX,centerOfDotY,6,0,Math.PI*2,true); if (count<6){ switch (count) { case 1: case 2: case 3: ctx.fillStyle="#FF0000"; break; default: ctx.fillStyle="#F9AF00"; break; } }else{ ctx.fillStyle="#FFF"; ctx.strokeStyle="#13B74B"; ctx.shadowColor = "#a8bbaa"; ctx.shadowBlur = 15; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; ctx.stroke(); } ctx.fill(); ctx.closePath(); ctx.shadowBlur =0; }; let count=0; for (let i = startAngleIndex; i <= endAngleIndex; i += step) { let angle = i * Math.PI; count++; this.DrawTick(angle,count); } }; //draw numbers let DrawDigits = function () { let angleIndex = startAngleIndex; digits.forEach(function (digit) { let angle = angleIndex * Math.PI, x = middleX + (radius - digitsOffsetFromArc) * Math.cos(angle), y = middleY + (radius - digitsOffsetFromArc) * Math.sin(angle); angleIndex += step; ctx.font = digitsFont; ctx.fillStyle = digitsColor; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillText(digit, x, y); }); }; /*draw arrow РИСОВАНИЕ СТРЕЛКИ*/ let DrawArrow = function () { let arrowAngle = arrowValueIndex * Math.PI; let toX = middleX + (radius) * Math.cos(arrowAngle)+50; let toY = middleY + (radius) * Math.sin(arrowAngle)-50; ctx.beginPath(); ctx.moveTo(middleX, middleY); ctx.lineTo(toX, toY); ctx.strokeStyle = arrowColor; ctx.lineWidth = arrowWidth; ctx.stroke(); ctx.closePath(); }; window.onload=()=>{ DrawZones(); DrawTicks(); DrawDigits(); DrawArrow(); }; </script> </body> </html>