You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用requestAnimationFrame实现矩形循环旋转动画?

实现Canvas矩形循环旋转动画

我来帮你搞定这个循环旋转的动画效果!你的基础代码已经具备了旋转的核心逻辑,只需要补上requestAnimationFrame的循环控制逻辑,让角度持续更新并循环重绘画面就可以了。

问题分析

原代码只绘制了一次固定角度的旋转矩形,没有实现角度的动态变化和画面的持续重绘,所以看不到动画效果。我们需要补充以下关键环节:

  • 一个跟踪当前旋转角度的变量
  • 由requestAnimationFrame驱动的循环函数
  • 每次循环更新角度后,完整重绘画布(避免残留绘制痕迹)
  • 角度超出360度时重置,实现循环效果

修改后的完整代码

const canvas = document.getElementById("canvas")
const ctx = canvas.getContext('2d')
const width = canvas.width
const height = canvas.height
const backgroundColor = '#c35033'
const overlayColor = '#bcddda'

// 定义当前旋转角度,初始值设为0
let currentAngle = 0;

// 启动动画循环
requestAnimationFrame(animate);

function animate() {
    // 1. 先清除画布并重绘背景,避免旋转轨迹残留
    fillRectangle(ctx, backgroundColor, 0, 0, width, height);

    // 2. 更新旋转角度:每次增加0.05弧度(可调整数值控制旋转速度)
    currentAngle += 0.05;
    // 3. 角度循环:超过2π(对应360度)时重置为0
    if (currentAngle > Math.PI * 2) {
        currentAngle = 0;
    }

    // 4. 绘制当前角度的青色旋转矩形
    fillSemiTransparentOverlay(currentAngle, width, overlayColor);

    // 5. 递归调用,让动画持续运行
    requestAnimationFrame(animate);
}

function fillSemiTransparentOverlay(angle, width, overlayColor) {
    ctx.save()
    ctx.translate(width / 2, width / 2)
    ctx.rotate(angle)
    ctx.translate(-width / 2, -width / 2)
    ctx.fillStyle = overlayColor
    ctx.fillRect(-width * (3 / 2), -width / 2, width * 2, width * 2)
    ctx.restore()
}

function fillRectangle(context, color, x, y, width, height) {
    context.fillStyle = color
    context.fillRect(x, y, width, height)
}
<canvas id="canvas" width="500" height="500" />

关键细节解释

  • 角度动态更新:用currentAngle变量记录当前旋转状态,每次循环增加一个小弧度值,数值越大旋转速度越快。
  • 画布重绘逻辑:每次动画循环都要先重绘背景,否则旋转的矩形会在画布上留下连续轨迹,导致画面混乱。
  • 循环角度控制:当角度超过Math.PI * 2(对应360度)时重置为0,确保旋转动作无限循环。
  • requestAnimationFrame优势:通过递归调用animate函数,让浏览器以设备最优帧率(通常60fps)执行动画,比setInterval更流畅且更节省系统资源。

可选优化:基于时间的速度控制

如果想让旋转速度在不同帧率的设备上保持一致,可以改用时间差计算角度增量:

// 在animate函数外记录起始时间
let lastTime = 0;

function animate(timestamp) {
    // 计算两次调用的时间差
    const deltaTime = timestamp - lastTime;
    lastTime = timestamp;

    // 基于时间更新角度:比如每秒旋转π弧度(180度)
    currentAngle += (Math.PI / 1000) * deltaTime;
    // ... 其他代码保持不变
}

内容的提问来源于stack exchange,提问作者user9944766

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:08:32