Javascript提高:requestAnimationFrame及圆类的简单动画-A 由Deepseek产生
·
关于 requestAnimationFrame
requestAnimationFrame 是浏览器提供的一个专门用于动画的 API。它的作用是在下一次浏览器重绘之前调用指定的回调函数,通常以每秒 60 次(取决于屏幕刷新率)的频率执行,从而实现流畅的动画。
主要特点:
- 与屏幕刷新率同步:避免不必要的绘制,减少 CPU/GPU 消耗。
- 自动暂停:当页面切换到后台标签页时,
requestAnimationFrame会暂停,节省资源。 - 精确时间控制:回调函数会收到一个
DOMHighResTimeStamp参数(从页面加载开始的时间戳),方便计算时间差实现匀速运动。 - 替代
setInterval/setTimeout:更高性能,更适合动画。
基本用法:
function animate() {
// 更新动画状态(如改变位置、旋转角度等)
// 绘制新的一帧
requestAnimationFrame(animate); // 递归调用,形成运动循环
}
requestAnimationFrame(animate); // 启动动画
通常还需要配合 cancelAnimationFrame 来停止动画。
简单动画案例:使用 Circle 类
下面通过三个简单案例演示如何使用 requestAnimationFrame 控制圆类的运动。每个案例都包含一个 Circle 类,并在 Canvas 上绘制动画。
基础 Circle 类定义
class Circle {
constructor(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
}
draw(ctx) {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
}
案例 1:圆在水平方向来回移动(边界反弹)
<canvas id="canvas1" width="600" height="200" style="border:1px solid #ccc"></canvas>
<script>
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
class Circle {
constructor(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
}
draw(ctx) {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
}
const circle = new Circle(50, 100, 20, 'blue');
let speedX = 3;
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 更新位置
circle.x += speedX;
// 边界反弹(碰到左右边界反转速度)
if (circle.x + circle.radius > canvas.width || circle.x - circle.radius < 0) {
speedX = -speedX;
}
circle.draw(ctx);
requestAnimationFrame(animate);
}
animate();
</script>
案例 2:圆的半径周期性变化(缩放动画)
<canvas id="canvas2" width="600" height="200" style="border:1px solid #ccc"></canvas>
<script>
const canvas = document.getElementById('canvas2');
const ctx = canvas.getContext('2d');
class Circle {
constructor(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
}
draw(ctx) {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
}
const circle = new Circle(300, 100, 20, 'green');
let radiusDelta = 0.5;
let minRadius = 10;
let maxRadius = 40;
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 改变半径
circle.radius += radiusDelta;
if (circle.radius > maxRadius || circle.radius < minRadius) {
radiusDelta = -radiusDelta;
}
circle.draw(ctx);
requestAnimationFrame(animate);
}
animate();
</script>
案例 3:画笔跟随鼠标移动(圆跟随鼠标 + 颜色渐变)
<canvas id="canvas3" width="600" height="200" style="border:1px solid #ccc"></canvas>
<script>
const canvas = document.getElementById('canvas3');
const ctx = canvas.getContext('2d');
class Circle {
constructor(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
}
draw(ctx) {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
}
const circle = new Circle(300, 100, 25, 'red');
// 监听鼠标移动
canvas.addEventListener('mousemove', (e) => {
const rect = canvas.getBoundingClientRect();
circle.x = e.clientX - rect.left;
circle.y = e.clientY - rect.top;
// 动态改变颜色(基于鼠标 X 坐标)
const hue = (circle.x / canvas.width) * 360;
circle.color = `hsl(${hue}, 100%, 50%)`;
});
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
circle.draw(ctx);
requestAnimationFrame(animate);
}
animate();
</script>
总结
requestAnimationFrame是现代浏览器实现流畅动画的标准方法,尤其适合与 Canvas 或 WebGL 结合使用。- 通过封装一个
Circle类,可以轻松管理圆的位置、半径、颜色等属性,并在每一帧更新这些属性,实现丰富多彩的动画效果。 - 以上三个案例分别演示了 位移、缩放和鼠标交互,可作为进一步开发复杂动画的基础。
更多推荐



所有评论(0)