- Tham gia
- 28/02/2015
- Bài viết
- 17,142
- Được Like
- 12,745
Sử dụng HTML5 canvas để tạo animation
RequestAnimationFrame là hàm sẽ được sử dụng thay cho những hàm trước đây ta thường dùng là setTimeout hay setInterval, trước tiên ta sẽ sơ lược qua về các cách thức tạo animation trong javaScript. setInterval sẽ thực hiện lặp đi lặp lại mãi mãi với mỗi thời gian nhất định cho tới khi ta gọi clearInterval để dừng nó. SetTimeout sẽ tạo delay trước khi thực hiện một chức năng nào đó kết hợp dùng đệ quy chúng ta cũng có lại cái lặp đi lặp lại mãi mãi với mỗi thời gian nhất định.
Sự mượt mà của ứng dụng animation của bạn dựa vào tỉ lệ khung hình trên mỗi giây, thông thường các màn hình của chúng ta có tỷ lệ làm tươi là 60Hz nên chúng ta có tỷ lệ khung hình nhanh nhất là 60fps, điều này có nghĩa trong javaScipt độ mượt tối đa có thể thực hiện được khi gọi setInterval với một khoảng thời gian là khoảng 17ms (1000ms / 60(fps) = 16.7ms).
Có vài lý do mà hiện người ta không còn hài lòng với setTimeout và setInterval, chẳng hạn như nó làm CPU của bạn vất cả hơn và khi trang đang được ẩn trong tab thì CPU vẫn phải hoạt động cho ứng dụng của bạn, với trình duyệt Chrome thì nó đã được chỉnh lại setTimeout và setInterval tới 1fps trong các tab ẩn, còn các trình duyệt khác thì không biết thế nào. Để có những animation tốt hơn Mozilla đã đề xuất sử dụng requestAnimationFrame và hiện nó đã trở thành API của trình duyệt và đang có mặt trên hầu hết các trình duyệt hiện đại, IE được hỗ trợ từ phiên bản 10, xem thêm ai hỗ trợ ở caniuse. Với requestAnimationFrame chúng ta không còn phải khai báo thời gian cho mỗi khung hình nữa mà đã được tối ưu hóa dựa trên tỷ lệ làm mới của màn hình, nó tận dụng được sức mạnh của GPU giúp animation trở nên mượt mà hơn hẳn.
Vì mỗi trình duyệt sẽ có một tiếp đầu ngữ riêng nên cần phải kiểm tra trước khi dùng:
RequestAnimationFrame sẽ trả về một ID và cứ tăng dần khi requestAnimationFrame được gọi lại, để hủy requestAnimationFrame chúng ta cần tới cancelAnimationFrame(ID). Hãy xem xét 1 ví dụ sau để biết cách xây dựng một hàm tạo animate cho ứng dụng. Trước tiên ta có một hình chữ nhật trong canvas với các thông số được lưu trữ trong một biến/đối tượng, requestAnimationFrame sẽ vẽ lại nó liên tục.
Tiếp theo sẽ là một hàm với một vài tham số cần thiết để hình chữ nhật thay đổi theo một thời gian nào đó:
Trong hàm step() ở trên có lẽ cần phải nói thêm về cách tính và ý nghĩa của biến progress. Trong hàm Math.min giá trị lớn nhất có thể trả về là 1, ở tham số đầu tiên của Math.min vì biến timestamp sẽ có giá trị tăng dần theo thời gian, nên kết quả của (end - timestamp) là khoảng thời gian còn lại và (duration - (end - timestamp) là khoảng thời gian đã trôi qua, kết quả ta được biến progress sẽ nhận giá trị từ 0 tới 1 lợi dụng điều này chúng ta cập nhật được trạng thái của hình chữ nhật. Xem ví dụ nguồn tại đây.
Chúc các bạn thành công.
RequestAnimationFrame là hàm sẽ được sử dụng thay cho những hàm trước đây ta thường dùng là setTimeout hay setInterval, trước tiên ta sẽ sơ lược qua về các cách thức tạo animation trong javaScript. setInterval sẽ thực hiện lặp đi lặp lại mãi mãi với mỗi thời gian nhất định cho tới khi ta gọi clearInterval để dừng nó. SetTimeout sẽ tạo delay trước khi thực hiện một chức năng nào đó kết hợp dùng đệ quy chúng ta cũng có lại cái lặp đi lặp lại mãi mãi với mỗi thời gian nhất định.
Sự mượt mà của ứng dụng animation của bạn dựa vào tỉ lệ khung hình trên mỗi giây, thông thường các màn hình của chúng ta có tỷ lệ làm tươi là 60Hz nên chúng ta có tỷ lệ khung hình nhanh nhất là 60fps, điều này có nghĩa trong javaScipt độ mượt tối đa có thể thực hiện được khi gọi setInterval với một khoảng thời gian là khoảng 17ms (1000ms / 60(fps) = 16.7ms).
Có vài lý do mà hiện người ta không còn hài lòng với setTimeout và setInterval, chẳng hạn như nó làm CPU của bạn vất cả hơn và khi trang đang được ẩn trong tab thì CPU vẫn phải hoạt động cho ứng dụng của bạn, với trình duyệt Chrome thì nó đã được chỉnh lại setTimeout và setInterval tới 1fps trong các tab ẩn, còn các trình duyệt khác thì không biết thế nào. Để có những animation tốt hơn Mozilla đã đề xuất sử dụng requestAnimationFrame và hiện nó đã trở thành API của trình duyệt và đang có mặt trên hầu hết các trình duyệt hiện đại, IE được hỗ trợ từ phiên bản 10, xem thêm ai hỗ trợ ở caniuse. Với requestAnimationFrame chúng ta không còn phải khai báo thời gian cho mỗi khung hình nữa mà đã được tối ưu hóa dựa trên tỷ lệ làm mới của màn hình, nó tận dụng được sức mạnh của GPU giúp animation trở nên mượt mà hơn hẳn.
Vì mỗi trình duyệt sẽ có một tiếp đầu ngữ riêng nên cần phải kiểm tra trước khi dùng:
Mã:
var vendors = ['ms', 'moz', 'webkit', 'o'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] ||
window[vendors[x]+'CancelRequestAnimationFrame'];
}
RequestAnimationFrame sẽ trả về một ID và cứ tăng dần khi requestAnimationFrame được gọi lại, để hủy requestAnimationFrame chúng ta cần tới cancelAnimationFrame(ID). Hãy xem xét 1 ví dụ sau để biết cách xây dựng một hàm tạo animate cho ứng dụng. Trước tiên ta có một hình chữ nhật trong canvas với các thông số được lưu trữ trong một biến/đối tượng, requestAnimationFrame sẽ vẽ lại nó liên tục.
Mã:
// Các thông số của hình chữ nhật
var square = {
'x': 50,
'y': 50,
'width': 100,
'height': 100
};
var render = function() {
// xóa toàn bộ vùng vanvas
context.clearRect(0, 0, canvas.width, canvas.height);
// vẽ hình chữ nhật
context.fillRect(square.x, square.y, square.width, square.height);
// vẽ lại liên tục
requestAnimationFrame(render);
};
render();
Tiếp theo sẽ là một hàm với một vài tham số cần thiết để hình chữ nhật thay đổi theo một thời gian nào đó:
Mã:
var animate = function(prop, val, duration) {
// Thời gian bắt đầu
var start = new Date().getTime();
// Thời điểm kết thúc
var end = start + duration;
// Trạng thái ban đầu của hình chữ nhật
var current = square[prop];
// Khoảng thay đổi của hình chữ nhật
var distance = val - current;
var step = function() {
// Thời gian hiện tại
var timestamp = new Date().getTime();
var progress = Math.min((duration - (end - timestamp)) / duration, 1);
// Cập nhật trạng thái cho hình chữ nhật
square[prop] = current + (distance * progress);
// Tới 1 thì dừng lặp step để kết thúc animation
if (progress < 1){
requestAnimationFrame(step);
}
};
return step();
};
animate('x', 0, 1000);
Trong hàm step() ở trên có lẽ cần phải nói thêm về cách tính và ý nghĩa của biến progress. Trong hàm Math.min giá trị lớn nhất có thể trả về là 1, ở tham số đầu tiên của Math.min vì biến timestamp sẽ có giá trị tăng dần theo thời gian, nên kết quả của (end - timestamp) là khoảng thời gian còn lại và (duration - (end - timestamp) là khoảng thời gian đã trôi qua, kết quả ta được biến progress sẽ nhận giá trị từ 0 tới 1 lợi dụng điều này chúng ta cập nhật được trạng thái của hình chữ nhật. Xem ví dụ nguồn tại đây.
Chúc các bạn thành công.
Nguồn: sothichweb.com
Bài viết liên quan
Bài viết mới