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()

Giới thiệu linear(), một hàm gia tốc trong CSS có thể 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à đàn hồi.

Hiệu ứng chuyển động trong CSS

Khi tạo hiệu ứng độ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 giá trị bằng hàm gia tốc 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 chế độ cài đặt sẵn 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 sử dụng phương pháp dựa trên các bước bằng hàm gia tốc steps().

Khi được sử dụng một cách thích hợp, các đường cong tăng tốc sẽ mang lại cho phần tử động cảm giác về trọng lượng khi phần tử đó dường như đang tăng tốc.

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ể tạo ra các đường cong gần giống một cách đáng kinh ngạc.

Giới thiệu về linear()

Browser Support

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

Source

Một cách mới để xác định gia tốc 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ố duy nhất trong khoảng 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 phân bổ cách đều nhau. Trong đoạn mã trước đó, điều này có nghĩa là giá trị đầu ra của 0.25 sẽ được dùng ở mốc 50%.

Biểu đồ cho linear(0, 0.25, 1) có dạng như sau:

Hình ảnh trực quan dạng biểu đồ của linear(0, 0,25, 1).

Nếu không muốn các điểm dừng được phân bổ đều nhau, bạn có thể truyền vào độ dài của điểm dừng (không bắt buộc). Khi truyền một giá trị làm độ dài của điểm dừng, bạn sẽ xác định điểm xuất phát của giá trị đó:

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

Ở đây, giá trị đầu ra 0.25 sẽ không được dùng tại dấu 50%, nhưng sẽ được dùng tại dấu 75%.

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

Khi chỉ định hai giá trị làm độ dài của điểm dừng, bạn sẽ 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 dùng từ 25% đến 75% thời gian.

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

Tạo đường cong phức tạp

Mặc dù các ví dụ trước là các đường cong gia tốc đơn giản hơn, nhưng bạn có thể dùng linear() để tạo lại các hàm gia tốc phức tạp nếu chấp nhận giảm bớt độ chính xác.

Hãy xem xét đường cong gia tốc nảy, một loại gia tốc 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, nhưng hình ảnh trực quan thì có thể. Sau đây là kết quả đầu ra, được trực quan hoá dưới dạng một đường cong màu xanh dương:

Một đường cong nảy mượt mà đượ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 đó. Trong đó, mỗi dấu chấm màu xanh lục biểu thị một điểm dừng:

Đường cong nảy mượt mà màu xanh dương, với các dấu chấm màu xanh lục được đặt ở trên.

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ạnh sẽ hơi thô hơn.

Đường cong đơn giản màu xanh lục được đặt lên trên đường cong mượt mà ban đầu màu xanh dương.

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

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

Đường cong mới, 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 sẽ có được kết quả mượt mà.

Mã dùng để tạo hiệu ứng chuyển độ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
);

Công cụ trợ giúp

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

Công cụ tạo đường cong chuyển động tuyến tính.
Ảnh chụp màn hình của https://linear-easing-generator.netlify.app/ đang hoạt động.

Công cụ này lấy hàm làm mịn JavaScript hoặc đường cong SVG làm thông tin đầu vào và xuất đường cong đã đơn giản hoá bằng cách sử dụng linear(). Sử dụng các thanh trượt để kiểm soát số lượng điểm dừng 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 sẵn: Lò xo, Nảy, Đàn hồi đơn giản hoặc Giảm tốc nhấn mạnh theo Material Design.

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

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

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

Tính năng này của Công cụ cho nhà phát triển có trong Công cụ cho nhà phát triển từ Chrome 114.