Ảnh động trên web – element.animate() hiện đã có trong Chrome 36

Brendan Kenny
Brendan Kenny

Ảnh động trên web đã từng là một tỉnh của JavaScript, nhưng khi thế giới chuyển sang thiết bị di động, các ảnh động đã chuyển sang CSS cho cú pháp khai báo và các trình duyệt tối ưu hóa có thể sử dụng nó. Với tốc độ 60 khung hình/giây trên thiết bị di động, bạn không nên dừng lại ở những trình duyệt biết cách hiển thị hiệu quả.

Ngày càng có nhiều công cụ giúp ảnh động dựa trên JavaScript trở nên hiệu quả hơn, nhưng giải pháp nhỏ gọn là sự hợp nhất giữa ảnh động khai báo và bắt buộc , trong đó quyết định về cách viết ảnh động dựa trên mã rõ ràng nhất, chứ không phải mã có thể thực hiện ở dạng này và không phải ở dạng khác.

Ảnh động trên web đã có mặt trong Chrome 36 dưới dạng element.animate(). Hàm mới này cho phép bạn tạo ảnh động hoàn toàn trong JavaScript và chạy hiệu quả như bất kỳ Ảnh động hoặc Chuyển đổi CSS nào (trên thực tế, kể từ Chrome 34, công cụ tạo Ảnh động trên web chính xác hỗ trợ tất cả các phương thức này).

Cú pháp đơn giản và các phần của cú pháp này chắc hẳn quen thuộc với bạn nếu bạn đã từng viết một CSS Transition hoặc Animation:

element.animate([
    {cssProperty: value0},
    {cssProperty: value1},
    {cssProperty: value2},
    //...
], {
    duration: timeInMs,
    iterations: iterationCount,
    delay: delayValue
});

Ưu điểm lớn nhất của chức năng mới này là loại bỏ rất nhiều vòng lặp khó hiểu mà trước đây chúng tôi phải chuyển qua để có được ảnh động mượt mà, không bị giật.

Ví dụ: đối với Ông già Noel năm ngoái, chúng tôi muốn tuyết rơi liên tục nên đã quyết định tạo ảnh động thông qua CSS để thực hiện hiệu quả.

Tuy nhiên, chúng ta muốn tự động chọn vị trí tuyết rơi dựa trên màn hình và các sự kiện diễn ra trong chính cảnh đó, và tất nhiên là chiều cao của tuyết rơi (chiều cao của cửa sổ trình duyệt của người dùng) sẽ không được xác định cho đến khi chúng ta thực sự chạy. Điều này có nghĩa là chúng tôi thực sự phải sử dụng Chuyển đổi CSS, vì việc tạo Ảnh động CSS trong thời gian chạy rất nhanh chóng phức tạp (và hàng trăm bông tuyết đồng nghĩa với hàng trăm quy tắc tạo kiểu mới).

Vì vậy, chúng tôi đã áp dụng phương pháp quen thuộc sau đây:

snowFlake.style.transform = 'translate(' + snowLeft + 'px, -100%)';
// wait a frame
snowFlake.offsetWidth;
snowFlake.style.transitionProperty = 'transform';
snowFlake.style.transitionDuration = '1500ms';
snowFlake.style.transform = 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)';

Điều này nằm ở nhận xét "chờ một khung". Để bắt đầu chuyển đổi thành công, trình duyệt phải xác nhận rằng phần tử này đang ở vị trí bắt đầu. Có một số cách để thực hiện việc này. Một trong những cách phổ biến nhất là đọc từ một trong các thuộc tính phần tử buộc trình duyệt tính toán bố cục, nhờ đó đảm bảo biết phần tử đó có vị trí bắt đầu trước khi chuyển sang vị trí kết thúc. Việc sử dụng phương pháp này cho phép bạn tự chúc mừng mình về kiến thức vượt trội của mình về nội bộ trình duyệt trong khi vẫn cảm thấy bẩn với mỗi lần nhấn phím.

Ngược lại, lệnh gọi element.animate() tương đương không thể rõ ràng hơn, cho biết chính xác mục đích:

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);

Có nhiều tuỳ chọn khác. Giống như các đối tác CSS, Hoạt ảnh web có thể bị trì hoãn và lặp lại:

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], {
    duration: 1500,
    iterations: 10,
    delay: 300
});

AnimationPlayer

element.animate() thực sự trả về một đối tượng AnimationPlayer. Việc này ngày càng trở nên quan trọng khi có thêm thông số kỹ thuật về Hoạt ảnh trên web được triển khai. Cả hoạt ảnh do JavaScript và CSS tạo đều sẽ có AnimationPlayers được liên kết, cho phép kết hợp liền mạch theo cách hữu ích và thú vị.

Mặc dù hiện tại, AnimationPlayer chỉ có hai phần chức năng, cả hai phần đều rất hữu ích. Bạn có thể huỷ ảnh động bất cứ lúc nào bằng cách sử dụng AnimationPlayer.cancel():

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
// less than 1500ms later...changed my mind
player.cancel();

Ngoài ra, để giải quyết vấn đề cho những người đã cố gắng xây dựng hệ thống ảnh động xung quanh Ảnh động CSS hoặc Chuyển đổi trước đây, Ảnh động trên web luôn kích hoạt một sự kiện khi hoàn tất:

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
player.onfinish = function(e) {
    console.log('per aspera ad terra!');
}

Dùng thử

Tất cả thông tin này đều được chuyển sang Chrome 36, chuyển sang bản thử nghiệm ngay hôm nay! Nếu bạn muốn dùng thử, hãy thử làm việc với phương thức triển khai gốc trong Chrome 36. Tuy nhiên, có một hình thức polyfill Ảnh động trên web, cung cấp phần lớn hơn đáng kể thông số kỹ thuật của Ảnh động trên web đầy đủ cho bất kỳ trình duyệt hiện đại, thường xuyên dùng nào.

Bạn có thể dùng bản minh hoạ hiệu ứng tuyết để thử sử dụng cả phiên bản gốc của element.animate()polyfill.

Hãy chia sẻ với chúng tôi cảm nhận của bạn

Mặc dù vậy, đây thực sự là bản xem trước những tính năng sắp ra mắt và được phát hành riêng ngay lập tức để lấy phản hồi của nhà phát triển. Chúng tôi vẫn chưa chắc chắn liệu mình đã đạt đến mọi trường hợp sử dụng hay chưa hoặc đã xem xét kỹ lưỡng mọi cạnh thô của các API hiện tại cho ảnh động. Cách duy nhất để chúng tôi biết và thực sự đưa ra giải pháp đúng đắn là nhà phát triển phải dùng thử và cho chúng tôi biết suy nghĩ của họ.

Tất nhiên, các nhận xét về bài đăng này rất có giá trị. Bạn cũng có thể gửi các nhận xét về tiêu chuẩn này tới Nhóm hoạt động CSS và SVG thông qua danh sách gửi thư public-fx.

Bản cập nhật, tháng 10 năm 2014: Chrome 39 bổ sung tính năng hỗ trợ cho một số phương thức bổ sung liên quan đến việc điều khiển chế độ phát, chẳng hạn như play(), pause()reverse(). Thao tác này cũng hỗ trợ chuyển đến một điểm cụ thể trong dòng thời gian của ảnh động thông qua thuộc tính currentTime. Bạn có thể xem chức năng này trong thực tế trong bản minh hoạ mới này.

Cảm ơn Addy Osmani và Max Heinritz đã hỗ trợ chúng tôi trong bài đăng này.