안녕하세요. 이것은 Alipay의 Sesame 신용 점수를 모방한 캔버스입니다. 실제로는 애니메이션 대시보드입니다.
우선 위 원본 사진:
낮은 점수가 웃음을 자아냅니다. 그런 다음 캔버스를 사용하여 달성한 렌더링을 살펴보세요.
<canvas id="canvas" width="400" height="700" data-score='724'></canvas> <!-- 设置data-score,分数区间[400, 900] -->
아, 그런 느낌이 아니네요. GIF 이미지이므로 웹페이지에서 열면 효과가 더 좋을 수도 있습니다(물론 그럴 수도 있습니다). 하단을 클릭하시면 codepen의 데모를 미리 보실 수 있습니다. 두 가지 결함이 있는데, 하나는 Sesame Credit 다이얼의 스케일이 실제로 균일하지 않다는 것입니다. 다른 하나는 다이얼의 움직이는 포인트가 흐릿한 효과가 있다는 것입니다. 아, 그건 다음에 얘기하자.
다음으로 달성 방법에 대해 이야기하겠습니다. 첫 번째 단계인 국제 연습은 캔버스를 만드는 것입니다.
var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'), cWidth = canvas.width, cHeight = canvas.height;
그런 다음 다이얼을 그립니다. 비록 처녀자리는 아니지만 최대한 원본 그림과 일치해야 합니다. 환형 개구부의 각도는 얼마입니까? PS로 이동하여 측정하세요.
136°, 이 각도는 후속 계산을 용이하게 하기 위해 실제로 140°와 같습니다. 그런 다음 분수 세그먼트의 호는 다음과 같습니다.
var deg1 = Math.PI * 11 / 45
먼저 가운데에 반투명 스케일 레이어를 그립니다.
ctx.save(); //中间刻度层 ctx.beginPath(); ctx.strokeStyle = 'rgba(255, 255, 255, .2)'; ctx.lineWidth = 10; ctx.arc(0, 0, 135, 0, 11 * deg0, false); ctx.stroke(); ctx.restore();
그런 다음 6개의 스케일 선을 그리고 for 루프를 사용합니다. 이를 달성하려면
ctx.save(); // 刻度线 for (var i = 0; i < 6; i++) { ctx.beginPath(); ctx.lineWidth = 2; ctx.strokeStyle = 'rgba(255, 255, 255, .3)'; ctx.moveTo(140, 0); ctx.lineTo(130, 0); ctx.stroke(); ctx.rotate(deg1); } ctx.restore();
마찬가지로 큰 눈금을 5개의 작은 눈금으로 나눕니다.
ctx.save(); // 细分刻度线 for (i = 0; i < 25; i++) { if (i % 5 !== 0){ ctx.beginPath(); ctx.lineWidth = 2; ctx.strokeStyle = 'rgba(255, 255, 255, .1)'; ctx.moveTo(140, 0); ctx.lineTo(133, 0); ctx.stroke(); } ctx.rotate(deg1 / 5); } ctx.restore();
여기서는 눈금이 괜찮습니다. 텍스트로 눈금을 표시해야 합니다. 각 부분 부분별 학점 수준에 대한 자세한 내용은 코드를 참고하시기 바랍니다. 이는 scale 구현 원리와 유사하므로 자세한 내용은 다루지 않겠습니다. 이제 가장 중요한 것은 다이얼의 이동점을 구현하는 것입니다(어떻게 부르는지 모르므로 아래에서는 이동점이라고 부르겠습니다). 가장 바깥쪽 링 트랙에 그려진 원인 매우 작은 반경이며 캔버스에서 원을 구현하는 방법은 다음과 같습니다.
ctx.arc(x, y, radius, sAngle, eAngle, false);
X와 Y만 제어하면 움직입니다. 그리고 우리가 원하는 효과를 얻으세요. 따라서 움직이는 점 객체를 만듭니다.
function Dot() { this.x = 0; this.y = 0; this.draw = function (ctx) { ctx.save(); ctx.beginPath(); ctx.fillStyle = 'rgba(255, 255, 255, .7)'; ctx.arc(this.x, this.y, 3, 0, Math.PI * 2, false); ctx.fill(); ctx.restore(); }; } var dot = new Dot(), dotSpeed = 0.03, //控制动点的速度 angle = 0, //这个很关键,用来得到动点的坐标x, y credit = 400; //信用最低分数
점의 x, y 좌표를 얻는 방법은 무엇입니까? 그런 다음 전설적인 삼각함수를 사용해야 합니다.
위 그림을 통해
x = r * cos(angle), y = r * sin(angle)
JavaScript에서 점의 중심 좌표는 다음과 같습니다.
dot.x = radius * Math.cos(angle); //radius为最外层轨道的半径值 dot.y = radius * Math.sin(angle);
다음으로 우리는 이 각도를 얻어야 합니다. 이는 라디안과 점수 사이의 비례 관계를 통해 얻을 수 있습니다.
var aim = (score - 400) * deg1 / 100; if (angle < aim) { angle += dotSpeed; } dot.draw(ctx);
그런 다음 이동 점의 회전에 따라 중간 신용 점수가 변경되도록 하고 숫자 변경을 위해 텍스트()를 만듭니다. 이동점과 일치 점은 일관되어야 하며 이동점의 속도를 기준으로 수치 변화를 계산해야 합니다.
function text(process) { ctx.save(); ctx.rotate(10 * deg0); ctx.fillStyle = '#000'; ctx.font = '80px Microsoft yahei'; ctx.textAlign = 'center'; ctx.textBaseLine = 'top'; ctx.fillText(process, 0 ,10); ctx.restore(); } var textSpeed = Math.round(dotSpeed * 100 / deg1), if (credit < score - textSpeed) { credit += textSpeed; } else if (credit >= score - textSpeed && credit < score) { credit += 1; // 这里确保信用分数最后停下来是我们输入的分数 } text(credit);
결국 이 모든 것은 창을 놓아서 벗어날 수 없습니다. requestAnimationFrame()은 그리기 애니메이션을 제어하고 ctx.clearRect(0, 0, cWidth, cHeight)는 캔버스를 지웁니다.
글이 안 좋으면 그냥 보기만 하면 될 것 같아요. 제가 무슨 말을 해야 할지 모르는 제 말을 이해하는 것보다 코드를 이해하는 능력이 모두가 더 나을 거라고 생각해요.