[英]How to rotate a canvas circle continuously?
https://codepen.io/saketkr7/pen/KKmzXOV我有一个圆形画布,其中放置了 n 个项目,我想旋转放置的所有项目? 我怎样才能做到这一点?
[![`
const canvas = document.getElementById('myCanvas'); var items = ['a', 'b' , 'c', 'd', 'e', 'g']; const ctx = canvas.getContext('2d'); var n = 6; var numElements = 8; var angle = 0; var step = (2*Math.PI) / numElements; var rotateAngle = 36 * Math.PI / 180; for(var i = 0; i < numElements; i++) { var x = 500/2 + 100 * Math.cos(angle); var y = 500/2 + 100 * Math.sin(angle); console.log(x, y); ctx.beginPath(); ctx.arc(x, y, 10, 0, 2 * Math.PI); ctx.stroke(); angle += step; }
<!DOCTYPE html> <html> <body> <canvas id="myCanvas" width="500" height="500"> Your browser does not support the HTML canvas tag. </canvas> </body> </html>
使用requestAnimationFrame(callback) (rAF) 来渲染动画。
回调函数负责渲染每个动画帧。 在这种情况下,它将清除画布并绘制圆圈。
回调函数以毫秒(1/1000 秒)为单位获取时间。 您可以使用它来设置旋转角度。 第一个示例使用time
和恒定rate
来定义每秒的旋转次数。
在回调函数中,您需要通过调用 rAF 来请求新帧。
开始动画请求第一帧。
修改您的代码,使其成为可以为动画的每一帧调用的函数。 在示例中,您修改的代码位于函数drawCircles(angle)
,其中角度是以弧度为单位的当前旋转。
向它传递一个当前旋转的参数。
下面的代码段执行上面描述的操作。
const ctx = canvas.getContext('2d'); const rate = 0.2; // Number of rotations per second function drawCircles(angle) { var i = 0; const numElements = 8; const step = (2 * Math.PI) / numElements; ctx.beginPath(); while (i < numElements) { const x = ctx.canvas.width / 2 + 100 * Math.cos(angle + i * step); const y = ctx.canvas.height / 2 + 100 * Math.sin(angle + i * step); ctx.moveTo(x + 10, y); ctx.arc(x, y, 10, 0, 2 * Math.PI); i++; } ctx.stroke(); } requestAnimationFrame(renderLoop); // rAF to start animation function renderLoop(time) { // rAF callback ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); drawCircles(((time * Math.PI * 2) / 1000) * rate); requestAnimationFrame(renderLoop); // request next frame }
<canvas id = "canvas" width="220" height="220"></canvas>
在许多设备上,帧速率会非常稳定,您可以使用固定速率时间来获得更流畅的动画。 如下一个片段所示。 请注意,如果设备掉帧,时间会漂移。
const ctx = canvas.getContext('2d'); const rate = 0.2; // APPROX Number of rotations per second var frame = 0; // counts frames function drawCircles(angle) { var i = 0; const numElements = 8; const step = (2 * Math.PI) / numElements; ctx.beginPath(); while (i < numElements) { const x = ctx.canvas.width / 2 + 100 * Math.cos(angle + i * step); const y = ctx.canvas.height / 2 + 100 * Math.sin(angle + i * step); ctx.moveTo(x + 10, y); ctx.arc(x, y, 10, 0, 2 * Math.PI); i++; } ctx.stroke(); } requestAnimationFrame(renderLoop); // rAF to start animation function renderLoop() { // rAF callback ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); time = frame++ * (1000 / 60); // Assumes 60 fps drawCircles(((time * Math.PI * 2) / 1000) * rate); requestAnimationFrame(renderLoop); // request next frame }
<canvas id = "canvas" width="220" height="220"></canvas>
重新评论
@MDN.API.CanvasRenderingContext2D@ 不是 3D 的最佳选择。 最好的选择是使用 WebGL 但是 WebGL 有一个陡峭的学习曲线。
3D 可以在 2D API 上完成,但您需要在 JS 中实现所有 3D 渲染代码,这将比 WebGl 慢几个数量级。
下面的示例使用 2D 画布渲染以 3D 方式旋转的卡通阴影球体的旋转环。
这是最基本的示例,不支持相机、灯光、纹理等。
const ctx = canvas.getContext('2d'); const rate = 0.2; // APPROX Number of rotations per second const numCircles = 18; const perspectiveRange = 300; // dist between front and back planes const ringRadius = 60; // in pixels const circleRadius = 10; // in pixels. Radius of circle at z === 0 const colors = [["#B11", "#F22"], ["#DB0", "#FF0"]]; var frame = 0; // counts frames function drawCircles(angle, rotY) { // rotZ rotates around Y axis (in and out of screen) var i = 0; ctx.fillStyle = "#FF0"; const step = (2 * Math.PI) / numCircles; const circles = []; // The transform for y rotation const dx = Math.cos(rotY); const dy = Math.sin(rotY); // get 3D location of each circle while (i < numCircles) { const x = ringRadius * Math.cos(angle + i * step); const y = ringRadius * Math.sin(angle + i * step); circles.push({x: x * dx, y, z: x * dy, colIdx: i % 2}); i++; } // sort circles from back to front circles.sort((a, b) => bz - az); // center on canvas ctx.setTransform(1,0,0,1, ctx.canvas.width / 2, ctx.canvas.height / 2); // draw 3D circles with perspective for (const c of circles) { const col = colors[c.colIdx]; // Calculate perspective scale. The further from the front the // smaller the perspective scale const p = (perspectiveRange - cz) / perspectiveRange; // Scale radius, x, y pos and line with by perspective scale const r = Math.abs(p * circleRadius); const x = p * cx; const y = p * cy; ctx.lineWidth = 1.5 * p; // shaded color ctx.fillStyle = col[0]; ctx.beginPath(); ctx.arc(x, y, r, 0, 2 * Math.PI); ctx.fill(); ctx.stroke(); // highlight color ctx.fillStyle = col[1]; ctx.beginPath(); ctx.arc(x - r * 0.1, y - r * 0.1, r * 0.8, 0, 2 * Math.PI); ctx.fill(); ctx.fillStyle = "#FFFA"; ctx.beginPath(); ctx.arc(x - r * 0.3, y - r * 0.3, r * 0.3, 0, 2 * Math.PI); ctx.fill(); } // reset canvas transform ctx.setTransform(1,0,0,1,0, 0); } requestAnimationFrame(renderLoop); // rAF to start animation function renderLoop() { // rAF callback ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); time = frame++ * (1000 / 60); // Assumes 60 fps const ang = ((time * Math.PI * 2) / 1000) * rate drawCircles(ang, ang / 2); requestAnimationFrame(renderLoop); // request next frame }
<canvas id = "canvas" width="180" height="180"></canvas>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.