Tránh màu vẽ không cần thiết - Phiên bản GIF động

Việc tránh vẽ là rất quan trọng để đạt được tốc độ khung hình mượt mà, đặc biệt là trên thiết bị di động. Tuy nhiên, đôi khi, sơn xuất hiện ở những nơi khác thường nhất. Bài viết này xem xét lý do ảnh GIF động có thể gây ra các lượt vẽ không cần thiết và cách khắc phục đơn giản mà bạn có thể áp dụng.

Lớp lớp đáng yêu

Có thể bạn đã biết, các trình duyệt hiện đại có thể vẽ các nhóm phần tử DOM thành "hình ảnh" riêng biệt, được gọi là lớp. Đôi khi, có một lớp cho toàn bộ trang, đôi khi có hàng trăm lớp hoặc trong một số ít trường hợp – hàng nghìn lớp!

Khi các phần tử DOM được nhóm lại với nhau thành một lớp và một trong các phần tử thay đổi về mặt hình ảnh, chúng ta sẽ phải vẽ không chỉ phần tử đã thay đổi mà còn tất cả các phần tử khác trong lớp chồng lên phần tử đã thay đổi. Việc vẽ một đối tượng lên trên một đối tượng khác sẽ khiến các pixel bị ghi đè "mất" vĩnh viễn; nếu muốn lấy lại các pixel ban đầu, bạn cần vẽ lại các pixel đó.

Do đó, đôi khi chúng ta muốn tách biệt một phần tử với các phần tử khác để khi phần tử đó được vẽ, chúng ta sẽ không cần vẽ lại các phần tử khác chưa thay đổi. Ví dụ: khi kết hợp tiêu đề trang cố định với nội dung có thể cuộn, bạn phải vẽ lại tiêu đề mỗi khi nội dung cuộn, cũng như nội dung mới hiển thị. Bằng cách đặt tiêu đề trong một lớp riêng biệt, trình duyệt có thể tối ưu hoá thao tác cuộn. Khi bạn cuộn, trình duyệt có thể di chuyển các lớp xung quanh – có thể là nhờ GPU – và tránh vẽ lại một trong hai lớp.

Mỗi lớp bổ sung làm tăng mức sử dụng bộ nhớ và tăng hao tổn hiệu suất, vì vậy, mục tiêu là nhóm trang thành ít lớp nhất có thể trong khi vẫn duy trì hiệu suất tốt.

Tất cả những điều này có liên quan gì đến ảnh GIF động?

Hãy cùng xem hình ảnh này:

Một ứng dụng web được chia thành 4 lớp.
Hình 1: Một ứng dụng web được chia thành 4 lớp.

Đây là một cách thiết lập lớp tiềm năng cho một ứng dụng đơn giản. Có 4 lớp ở đây: 3 trong số đó (các lớp 2 đến 4) là các thành phần giao diện; lớp sau là trình tải, tình cờ là một ảnh GIF động. Trong luồng thông thường, bạn hiển thị trình tải (lớp 1) trong khi ứng dụng tải, sau đó khi mọi thứ hoàn tất, bạn sẽ hiển thị các lớp khác. Nhưng điều quan trọng là bạn cần ẩn ảnh GIF động.

Nhưng tại sao tôi cần phải ẩn nó?!

Đây là một câu hỏi hay. Trong trường hợp lý tưởng, trình duyệt sẽ chỉ kiểm tra chế độ hiển thị của ảnh GIF cho bạn và tránh tự động vẽ. Rất tiếc, việc kiểm tra xem ảnh GIF động có bị che khuất hay hiển thị trên màn hình hay không thường tốn kém hơn so với việc chỉ vẽ ảnh GIF đó. Vì vậy, ảnh GIF sẽ được vẽ.

Trong trường hợp tốt nhất, GIF nằm trong lớp riêng và trình duyệt chỉ cần vẽ và tải lên GPU. Nhưng trong trường hợp xấu nhất, tất cả các phần tử của bạn có thể được nhóm thành một lớp duy nhất và trình duyệt phải vẽ lại mọi phần tử. Và khi hoàn tất, ứng dụng vẫn cần tải mọi thứ lên GPU. Tất cả những việc này đều xảy ra cho mỗi khung hình GIF, mặc dù người dùng thậm chí không thể xem được GIF!

Trên máy tính, bạn có thể bỏ qua loại hành vi vẽ này vì CPU và GPU mạnh hơn và có nhiều băng thông để chuyển dữ liệu giữa hai thiết bị này. Tuy nhiên, trên thiết bị di động, việc vẽ sẽ tốn kém rất nhiều nên bạn phải hết sức cẩn thận.

Thay đổi này ảnh hưởng đến những trình duyệt nào?

Như thường lệ, hành vi của các trình duyệt sẽ khác nhau. Hiện tại, Chrome, Safari và Opera đều vẽ lại, ngay cả khi ảnh GIF bị che khuất. Mặt khác, Firefox nhận thấy rằng ảnh GIF bị che khuất và không cần vẽ lại. Internet Explorer vẫn là một hộp đen và ngay cả trong IE11 – vì các công cụ F12 vẫn đang được phát triển – không có dấu hiệu nào cho biết liệu có quá trình vẽ lại nào đang diễn ra hay không.

Làm cách nào để biết tôi có gặp vấn đề này không?

Cách dễ nhất là sử dụng tính năng "Hiển thị hình chữ nhật vẽ" trong Chrome DevTools. Tải DevTools và nhấn vào biểu tượng bánh răng ở góc dưới bên phải (Biểu tượng bánh răng) rồi chọn Show paint rectangles (Hiện hình chữ nhật vẽ) trong mục Rendering (Hiển thị).

Bật tuỳ chọn Hiển thị hình chữ nhật vẽ bên trong Chrome DevTools
Hình 2: Bật tuỳ chọn Show paint rectangles (Hiện hình chữ nhật vẽ) bên trong Chrome DevTools.

Giờ đây, bạn chỉ cần tìm một hình chữ nhật màu đỏ như sau:

Tính năng Hiển thị hình chữ nhật vẽ của DevTools gợi ý về các vấn đề với ảnh GIF động bằng hình chữ nhật màu đỏ.
Hình 3: Tính năng Show Paint Rectangles (Hiển thị hình chữ nhật vẽ) của DevTools gợi ý về các vấn đề với ảnh GIF động bằng hình chữ nhật màu đỏ.

Hộp nhỏ màu đỏ trên màn hình cho biết Chrome đang vẽ lại một nội dung nào đó. Bạn biết rằng có một ảnh GIF trình tải ẩn sau các phần tử khác, vì vậy, khi thấy một hộp màu đỏ như thế này, bạn cần ẩn các phần tử hiển thị và kiểm tra xem bạn đã để ảnh GIF động quay đi hay chưa. Nếu đã có, bạn cần thêm một số CSS hoặc JavaScript để áp dụng display: none hoặc visibility: hidden cho phần tử đó hoặc phần tử mẹ của phần tử đó. Tất nhiên, nếu đó chỉ là hình nền thì bạn nên nhớ xoá hình nền đó.

Nếu bạn muốn xem ví dụ về hành vi này trong một trang web đang hoạt động, hãy xem Allegro. Tại đây, hình ảnh của mỗi sản phẩm có một ảnh GIF trình tải bị che khuất thay vì bị ẩn rõ ràng.

Kết luận

Việc đạt được 60 khung hình/giây có nghĩa là chỉ làm những việc cần thiết để hiển thị trang và không làm gì khác. Việc loại bỏ sơn thừa là một bước quan trọng để đạt được mục tiêu này. Ảnh GIF động đang chạy có thể kích hoạt các lượt vẽ không cần thiết. Bạn có thể dễ dàng tìm thấy và gỡ lỗi bằng công cụ Hiển thị hình chữ nhật vẽ của DevTools.

Bạn không để ảnh GIF tải con mèo con động đó chạy mãi mãi, phải không?