Tạo các đường cong ảnh động phức tạp trong CSS bằng hàm gia tốc tuyến tính()

Ra mắt linear(), một hàm gia tốc trong CSS. Hàm này nội suy tuyến tính giữa các điểm, cho phép bạn tạo lại hiệu ứng độ nảy và hiệu ứng lò xo.

Hiệu ứng làm dịu trong CSS

Khi tạo ảnh động hoặc chuyển đổi các phần tử trong CSS, bạn có thể kiểm soát tốc độ thay đổi của một giá trị bằng hàm làm dịu bằng cách sử dụng các thuộc tính animation-timing-functiontransition-timing-function.

Có một số từ khoá có sẵn dưới dạng giá trị đặt trước trong CSS, cụ thể là linear, ease, ease-in, ease-outease-in-out. Để tạo đường cong gia tốc của riêng bạn, hãy sử dụng hàm cubic-bezier() hoặc thực hiện phương pháp theo bước bằng cách sử dụng hàm gia tốc steps().

Khi được sử dụng đúng cách, hiệu ứng làm dịu sẽ tạo cho phần tử ảnh động cảm giác nặng nề khi nó có vẻ như đang tích luỹ động lượng.

Bạn không thể tạo các đường cong phức tạp như hiệu ứng nảy hoặc lò xo trong CSS, nhưng nhờ linear(), giờ đây bạn có thể ước chừng các đường cong đó một cách đáng kinh ngạc.

Giới thiệu về linear()

Hỗ trợ trình duyệt

  • Chrome: 113.
  • Edge: 113.
  • Firefox: 112.
  • Safari: 17.2.

Một cách mới để xác định hiệu ứng làm dịu trong CSS là sử dụng linear(). Hàm này chấp nhận một số điểm dừng, được phân tách bằng dấu phẩy. Mỗi điểm dừng là một số từ 0 đến 1. Giữa mỗi điểm dừng, quá trình nội suy được thực hiện theo cách tuyến tính, giải thích tên của hàm.

animation-timing-function: linear(0, 0.25, 1);

Theo mặc định, các điểm dừng này được trải đều. Trong đoạn mã trước, điều đó có nghĩa là giá trị đầu ra của 0.25 sẽ được sử dụng ở mốc 50%.

Một cách trực quan, biểu đồ của linear(0, 0.25, 1) có dạng như sau:

Biểu đồ trực quan hoá tuyến tính(0, 0,25, 1).

Nếu không muốn các điểm dừng được trải đều, bạn có thể tuỳ ý truyền vào một độ dài điểm dừng. Khi truyền một giá trị dưới dạng độ dài điểm dừng, bạn sẽ xác định điểm bắt đầu của giá trị đó:

animation-timing-function: linear(0, 0.25 75%, 1);

Ở đây, giá trị đầu ra của 0.25 sẽ không được sử dụng tại điểm đánh dấu 50% mà là tại 75%.

Hình ảnh biểu đồ của hàm tuyến tính(0, 0,25 75%, 1).

Khi chỉ định hai giá trị làm độ dài điểm dừng, bạn xác định cả điểm bắt đầu và điểm kết thúc của điểm dừng đó:

animation-timing-function: linear(0, 0.25 25% 75%, 1);

Giá trị đầu ra là 0,25 sẽ được sử dụng từ 25% đến 75% theo thời gian.

Hình ảnh biểu đồ của hàm tuyến tính(0, 0,25 25% 75%, 1).

Tạo đường cong phức tạp bằng hàm tuyến tính()

Mặc dù các ví dụ trên là các hiệu ứng làm dịu rất đơn giản, nhưng bạn có thể sử dụng linear() để tạo lại các hàm làm dịu phức tạp theo cách rất đơn giản, với sự đánh đổi là mất một số độ chính xác.

Hãy lấy ví dụ về đường cong giảm độ nảy này, một loại độ giảm không thể biểu thị trực tiếp trong CSS, được xác định bằng JavaScript:

function easing(pos) {
  const t = 7.5625;
  const e = 2.75;
  return pos < 1 / e
    ? t * pos * pos
    : pos < 2 / e
    ? t * (pos -= 1.5 / e) * pos + 0.75
    : pos < 2.5 / e
    ? t * (pos -= 2.25 / e) * pos + 0.9375
    : t * (pos -= 2.625 / e) * pos + 0.984375;
}

Mặc dù mã có thể không cho bạn biết nhiều thông tin, nhưng hình ảnh trực quan có thể giúp bạn hiểu rõ hơn. Đây là kết quả, được minh hoạ dưới dạng đường cong màu xanh dương:

Đường cong tỷ lệ phần trăm thư bị trả về được vẽ bằng màu xanh dương.

Bạn có thể đơn giản hoá đường cong bằng cách thêm một số điểm dừng vào đường cong đó. Ở đây, mỗi dấu chấm màu xanh lục biểu thị một điểm dừng:

Một đường cong thoát mượt mà màu xanh dương, với các dấu chấm màu xanh lục nằm ở trên cùng.

Khi được truyền vào linear(), kết quả sẽ là một đường cong trông giống như đường cong ban đầu, nhưng có các cạnh hơi thô hơn.

Một đường cong được đơn giản hoá màu xanh lục nằm trên đường cong mượt mà ban đầu màu xanh dương.

So sánh hộp ảnh động màu xanh lục với hộp ảnh động màu xanh dương, bạn có thể thấy hộp ảnh động màu xanh lục không mượt mà bằng.

Tuy nhiên, nếu bạn thêm đủ số điểm dừng, bạn có thể ước chừng đường cong ban đầu khá chính xác. Sau đây là phiên bản đã cập nhật:

Một đường cong được cập nhật, với số điểm dừng gấp đôi.

Chỉ cần tăng gấp đôi số điểm dừng, bạn đã có được kết quả mượt mà.

Mã dùng để tạo ảnh động có dạng như sau:

animation-timing-function: linear(
  /* Start to 1st bounce */
  0, 0.004, 0.016, 0.035, 0.063 9.1%, 0.141, 0.25, 0.391, 0.563, 0.765, 1,
  /* 1st to 2nd bounce */
  0.891, 0.813 45.5%, 0.785, 0.766, 0.754, 0.75, 0.754, 0.766, 0.785, 0.813 63.6%, 0.891, 1 72.7%,
  /* 2nd to 3rd bounce */
  0.973, 0.953, 0.941, 0.938, 0.941, 0.953, 0.973, 1,
  /* 3rd bounce to end */
  0.988, 0.984, 0.988, 1
);

Một công cụ trợ giúp

Việc tạo danh sách điểm dừng này theo cách thủ công sẽ rất cồng kềnh. Rất may là JakeAdam đã tạo một công cụ giúp bạn chuyển đổi đường cong gia tốc sang đường cong tương ứng linear().

Ảnh chụp màn hình công cụ tạo hiệu ứng làm dịu tuyến tính.
Ảnh chụp màn hình https://linear-easing-generator.netlify.app/ đang hoạt động.

Công cụ này lấy hàm làm dịu JavaScript hoặc đường cong SVG làm dữ liệu đầu vào và xuất ra đường cong được đơn giản hoá bằng linear(). Sử dụng thanh trượt để kiểm soát số lượng điểm dừng mà bạn muốn và độ chính xác của các điểm dừng đó.

Ở trên cùng bên phải, bạn cũng có thể chọn một trong các chế độ cài đặt trước: Spring (Mùa xuân), Bounce (Độ nảy), Simple elastic (Độ đàn hồi đơn giản) hoặc Material Design emphasized easing (Độ giảm tốc nhấn mạnh trong Material Design).

Hỗ trợ Công cụ cho nhà phát triển

Công cụ cho nhà phát triển hỗ trợ trực quan hoá và chỉnh sửa kết quả của linear(). Hãy nhấp vào biểu tượng này để hiển thị một phần chú thích mang tính tương tác, giúp bạn kéo quanh các điểm dừng.

Ảnh chụp màn hình trình chỉnh sửa `linear()` của Công cụ của Chrome cho nhà phát triển.
Ảnh chụp màn hình trình chỉnh sửa "linear()" của Công cụ cho nhà phát triển của Chrome.

Tính năng này của DevTools có trong DevTools đi kèm với Chrome 114.

Ảnh chụp của Howie Mapson trên Unsplash