原生js实现动画
原生 JavaScript 实现动画的方法
使用 requestAnimationFrame
requestAnimationFrame 是浏览器提供的专门用于动画的 API,性能优于 setTimeout 或 setInterval。它会根据屏幕刷新率自动调整回调频率。
function animate() {
const element = document.getElementById('target');
let position = 0;
function step(timestamp) {
position += 1;
element.style.transform = `translateX(${position}px)`;
if (position < 200) {
requestAnimationFrame(step);
}
}
requestAnimationFrame(step);
}
animate();
使用 CSS transition 结合 JavaScript
通过 JavaScript 动态修改 CSS 属性,利用 CSS 的过渡效果实现动画。

const element = document.getElementById('target');
element.style.transition = 'transform 1s ease-in-out';
element.style.transform = 'translateX(200px)';
使用 CSS @keyframes 动画
定义关键帧动画并通过 JavaScript 控制其播放。

@keyframes slide {
from { transform: translateX(0); }
to { transform: translateX(200px); }
}
#target {
animation: slide 2s infinite;
}
const element = document.getElementById('target');
element.style.animationPlayState = 'paused'; // 暂停动画
element.style.animationPlayState = 'running'; // 继续动画
使用 setInterval 或 setTimeout
虽然不推荐,但可以通过定时器实现简单动画。
function animate() {
const element = document.getElementById('target');
let position = 0;
const intervalId = setInterval(() => {
position += 1;
element.style.transform = `translateX(${position}px)`;
if (position >= 200) {
clearInterval(intervalId);
}
}, 16); // 约 60fps
}
animate();
性能优化建议
- 使用
transform和opacity属性实现动画,这些属性不会触发重排(reflow),性能更好。 - 避免在动画中频繁修改
width、height、margin等会触发重排的属性。 - 使用
will-change提示浏览器元素即将发生变化,例如will-change: transform;。
复杂动画示例
以下是一个包含缓动函数的动画示例,模拟更自然的运动效果。
function animateWithEasing(element, duration, easingFunc) {
const startTime = performance.now();
const startPos = 0;
const endPos = 200;
function step(currentTime) {
const elapsedTime = currentTime - startTime;
const progress = Math.min(elapsedTime / duration, 1);
const easedProgress = easingFunc(progress);
const currentPos = startPos + (endPos - startPos) * easedProgress;
element.style.transform = `translateX(${currentPos}px)`;
if (progress < 1) {
requestAnimationFrame(step);
}
}
requestAnimationFrame(step);
}
function easeOutQuad(t) {
return t * (2 - t);
}
const element = document.getElementById('target');
animateWithEasing(element, 1000, easeOutQuad);
注意事项
- 动画结束后应清理资源,例如取消未完成的
requestAnimationFrame调用。 - 对于移动端,注意处理触摸事件与动画的冲突。
- 使用
window.matchMedia检测用户是否 prefers-reduced-motion,为对动画敏感的用户提供无障碍支持。






