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 easing trong CSS nội suy tuyến tính giữa các điểm của hàm, cho phép bạn tạo lại hiệu ứng nảy và 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 các đường cong chuyển động 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 chuyển động 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ự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ể ước chừng các đường cong đó 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.

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 con số 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 đặt cách đều nhau. 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%.

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

Hình ảnh biểu đồ của hàm 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ị làm độ dài điểm dừng, bạn 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 các đường cong phức tạp bằng linear()

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 đườ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. Dưới đây là kết quả, được minh hoạ dưới dạng một đườ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 thêm đủ điểm dừng, bạn có thể ước chừng khá chính xác đường cong ban đầu. Dưới đây là phiên bản cập nhật:

Một đường cong đã 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 sẽ 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, JakeAdam đã tạo ra một công cụ giúp bạn chuyển đổi một đường cong chuyển động mềm thành đối tác 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 có hỗ trợ để trực quan hoá và chỉnh sửa kết quả của linear(). Nhấp vào biểu tượng để hiện chú giải công cụ tương tác cho phép bạn kéo xung quanh các điểm dừng.

Ảnh chụp màn hình trình chỉnh sửa `linear()` của Chrome DevTools.
Ảnh chụp màn hình trình chỉnh sửa `linear()` của Chrome DevTools.

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