window.requestAnimationFrame()方法通知瀏覽器我們想要產生動畫,並且要求瀏覽器在下次重繪畫面前呼叫特定函數更新動畫。這個方法接受一個引數作為下次重繪前調用的回呼函數。
Note: 若是想要在下次重繪時產生另一個動畫,這個回呼函數內必須自行呼叫 requestAnimationFrame()。
當準備好更新頁面上的動畫時應當呼叫這個方法。這表示向瀏覽器請求在下次重繪前呼叫這個動畫函數。回呼的次數通常落在每秒 60 次,但通常會根據 W3C 的建議符合多數瀏覽器重新整理的頻率。當頁面處於背景或隱藏狀態時 <iframe> ,多數的瀏覽器會暫停 requestAnimationFrame() 的呼叫,從而改善效能表現及電池壽命。
回呼方法會得到一個 DOMHighResTimeStamp
的引數,作為指示目前的時間(基於 time origin 之後經過的毫秒數)。當 requestAnimationFrame()
佇列了數個回呼並且在同一幀開始觸發多個回呼時,儘管每一個之前的回呼在運作時會消耗一定的時間,但它們都會取得同樣的時間戳記。時間戳記是由十進位數字表示的毫秒且最小的精準度為 1 毫秒(1000 µs)。
requestAnimationFrame語法
window.requestAnimationFrame(callback);
callback
當下次重新繪製時用於呼叫並更新動畫。回呼函數會得到一個引數—— DOMHighResTimeStamp
——類似於由 performance.now()
回傳的結果,其用於指示當 requestAnimationFrame()
開始執行回呼函數的時間。
long
型別的整數值表示請求的 id,作為其進入回呼清單中的唯一識別。雖然回傳值是一個非零值,但不應該對其有其他任何的假設。將這個值傳遞給 window.cancelAnimationFrame()
可以取消重新整理頁面回呼的請求
var start = null;
var element = document.getElementById('canvas');
function step(timestamp) {
if (!start) start = timestamp;
var progress = timestamp - start;
element.style.transform = 'translateX(' + Math.min(progress / 10, 200) + 'px)';
if (progress < 2000) {
window.requestAnimationFrame(step);
}
}
window.requestAnimationFrame(step);
包括位置(x, y)、半徑(radius)、顏色(color)、繪製球函式(draw)
範例:繪製球物件 ex09-01.html ex09-01.js
var ball = {
x: 100,
y: 100,
radius: 25,
color: 'blue',
draw: function() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fillStyle = this.color;
ctx.fill();
}
};
x, y軸的位移 vx, vy
var ball = {
x: 100,
y: 100,
vx: 5,
vy: 2,
radius: 25,
color: 'blue',
draw: function() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fillStyle = this.color;
ctx.fill();
}
};
raf = window.requestAnimationFrame(draw);
window.cancelAnimationFrame(raf);
function draw() {
ctx.clearRect(0,0, canvas.width, canvas.height);
ball.draw();
ball.x += ball.vx;
ball.y += ball.vy;
raf = window.requestAnimationFrame(draw);
}
if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) {
ball.vy = -ball.vy;
}
if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) {
ball.vx = -ball.vx;
}
function draw() {
ctx.clearRect(0,0, canvas.width, canvas.height);
ball.draw();
ball.x += ball.vx;
ball.y += ball.vy;
// 反轉
if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) {
ball.vy = -ball.vy;
}
if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) {
ball.vx = -ball.vx;
}
raf = window.requestAnimationFrame(draw);
}
為了使移動看起來更真實,你可以照著範例改變速度: 會使每個幀(frame)的垂直向量減少,所以球將只會在地板彈跳直到結束。
ball.vy *= .99;
ball.vy += .25;
直到現在我們已經使用clearRect方法清除之前的幀(frames)。如果使用重置半透明fillRect這個方法,可以更淺顯的看出創造追蹤效果。
ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
為了能控制球使它跟著滑鼠移動,在這個範例使用mousemove 效果。當 click 事件觸發了這顆球,它又會開始彈跳。當滑鼠離開畫布mouseout的事件監聽副程式將結束彈跳。
canvas.addEventListener('mousemove', function(e) {
if (!running) {
clear();
ball.x = e.clientX;
ball.y = e.clientY;
ball.draw();
}
});
canvas.addEventListener('click', function(e) {
if (!running) {
raf = window.requestAnimationFrame(draw);
running = true;
}
});
canvas.addEventListener('mouseout', function(e) {
window.cancelAnimationFrame(raf);
running = false;
});