window.requestAnimationFrame() 方法用来页面重绘之前,通知浏览器调用指定的函数,以满足开发者的需求。
如果想得到连贯的逐帧动画,函数中必须重新调用 requestAnimationFrame() 。
requestID = window.requestAnimationFrame(callback);
/*
Firefox 23 / IE 10 / Chrome / Safari */
requestID = window.mozRequestAnimationFrame(callback);
/* Firefox < 23 */
requestID = window.webkitRequestAnimationFrame(callback);
/* Oldversions Chromes / webkit */
callback : 每次重新绘制,都会调用这个回调函数。这个回调函数会收到一个参数,这个 DOMHighResTimeStamp 类型的参数指示当前时间距离开始触发 requestAnimationFrame de 回调函数的时间。
返回值 requestId 是一个长整型的非零数值。作为一个唯一的标识符,可以将该值传递给 window.cancelAnimationFrame() 来取消这个回调函数。
function animation() {
/* some any code */ requestAnimationFrame(
animation,
); /* some animation code */
} /* request animation */
requestAnimationFrame(animation);
有时候需要控制,就需要句柄:
let globalID;
function animation() {
/* some any code */
globalID = requestAnimationFrame(animation);
/* some animation code*/
}
/* request animation*/
globalID = requestAnimationFrame(animation);
/* stop*/
cancelAnimationFrame(globalID);
初始 div 宽度为 1 px ,在 step() 函数中将进度加 1 ,然后更新到 div 宽度上,在进度达到 100 之前,一直重复这个过程:
window.requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
var start = null;
var ele = document.getElementById('test');
var progress = 0;
function step(timestamp) {
progress += 1;
ele.style.width = progress + '%';
ele.innerHTML = progress + '%';
if (progress < 100) {
requestAnimationFrame(step);
}
}
requestAnimationFrame(step);
document.getElementById('run').addEventListener(
'click',
function () {
ele.style.width = '1px';
progress = 0;
requestAnimationFrame(step);
},
false,
);
首先在页面中插入一个 <canvas id="motion">
标签;然后设计一块画布,在画布上随机生成一个圆点,颜色、运动方向随机;接着从画布中央随机向四周运动,同时逐步增大半径;最后调用
requestAnimationFrame() 方法,传递回调函数生成 animate() ,从而设计随机粒子放射运动的效果。
(function () {
'use strict';
var vendors = ['webkit', 'moz'];
for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
var vp = vendors[i];
window.requestAnimationFrame = window[vp + 'RequestAnimationFrame'];
window.cancelAnimationFrame =
window[vp + 'CancelAnimationFrame'] ||
window[vp + 'CancelRequestAnimationFrame'];
}
if (
/iP(ad|hone|od)._OS 6/.test(window.navigator.userAgent) || // iOS6 is buggy
!window.requestAnimationFrame ||
!window.cancelAnimationFrame
) {
var lastTime = 0;
window.requestAnimationFrame = function (callback) {
var now = Date.now();
var nextTime = Math.max(lastTime + 16, now);
return setTimeout(function () {
callback((lastTime = nextTime));
}, nextTime - now);
};
window.cancelAnimationFrame = clearTimeout;
}
})();
var getRandomColor = function () {
return '#' + ((Math.random() * 0xffffff) << 0).toString(16);
};
var canvas = document.getElementById('motion'),
c = canvas.getContext('2d'),
particles = {},
particleIndex = 0,
particleNum = 0.2;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
function Particle() {
this.x = canvas.width / 2;
this.y = canvas.height / 2;
this.vx = Math.random() * 6 - 3;
this.vy = Math.random() * 4 - 2;
this.growth = (Math.abs(this.vx) + Math.abs(this.vy)) * 0.007;
particleIndex++;
particles[particleIndex] = this;
this.id = particleIndex;
this.size = Math.random() * 1;
this.color = getRandomColor();
}
Particle.prototype.draw = function () {
this.x += this.vx;
this.y += this.vy;
this.size += this.growth;
if (this.x > canvas.width || this.y > canvas.height) {
delete particles[this.id];
}
c.fillStyle = this.color;
c.beginPath();
c.arc(this.x, this.y, this.size, 0 * Math.PI, 2 * Math.PI);
c.fill();
};
function animate() {
requestAnimationFrame(animate);
c.fillStyle = '#000';
c.fillRect(0, 0, canvas.width, canvas.height);
if (Math.random() > particleNum) {
new Particle();
}
for (var i in particles) {
particles[i].draw();
}
}
requestAnimationFrame(animate);
window.requestAnimFrame = (function () {
return (
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function () {
window.setTimeout(callback, 1000 / 60);
}
);
})();
var canvas, context;
init();
animate();
function init() {
canvas = document.createElement('canvas');
canvas.style.left = 0;
canvas.style.top = 0;
canvas.width = 210;
canvas.height = 210;
context = canvas.getContext('2d');
document.body.appendChild(canvas);
}
function animate() {
requestAnimFrame(animate);
draw();
}
function draw() {
var time = new Date().getTime() * 0.002;
var x = Math.sin(time) * 96 + 105;
var y = Math.cos(time * 0.9) * 96 + 105;
context.fillStyle = 'pink';
context.fillRect(0, 0, 255, 255);
context.fillStyle = 'rgb(255,0,0)';
context.beginPath();
context.arc(x, y, 10, 0, Math.PI * 2, true);
context.closePath();
context.fill();
}