Hàm Easing dựa trên vật lý

Tính năng web: Hàm easing linear()

Các hàm easing CSS truyền thống như ease-in hoặc cubic-bezier() chỉ giới hạn ở các đường cong đơn giản, nên không thể tạo ra các hiệu ứng phức tạp dựa trên vật lý như nảy hoặc lò xo. Hàm thời gian linear() giải quyết vấn đề này bằng cách cho phép bạn cung cấp một loạt điểm dừng có thể ước chừng các đường cong phức tạp. Hiệu ứng chuyển tiếp và ảnh động được nội suy dựa trên các đường thẳng giữa các điểm dừng, nhưng trong đủ điểm dừng, hiệu ứng này có thể xuất hiện mượt mà.

Các bước triển khai

  1. Tạo điểm dừng đường cong: Việc vẽ thủ công hàng chục điểm cho hiệu ứng lò xo hoặc nảy là không thực tế. Sử dụng hàm thời gian từ thư viện bên ngoài hoặc dùng một công cụ để chuyển đổi hàm easing JavaScript hiện có hoặc đường dẫn SVG thành cú pháp linear(). Không bắt buộc: lưu trữ các hàm thời gian này dưới dạng thuộc tính tuỳ chỉnh CSS để sử dụng lại trên toàn bộ trang web.
  2. Xác định hàm thời gian: Áp dụng các điểm dừng đã tạo cho thuộc tính transition-timing-function hoặc animation-timing-function, hoặc thông qua các ký hiệu viết tắt transition hoặc animation.
  3. Điều chỉnh thời lượng: Không giống như các công cụ vật lý JavaScript (trong đó thời lượng được lấy từ các thuộc tính vật lý như khối lượng, độ cứng), CSS vẫn yêu cầu một duration cố định. Bạn có thể cần điều chỉnh thời lượng để đạt được hiệu ứng mong muốn.

Ví dụ: Spring Easing

Ví dụ này cho thấy cách sử dụng hàm linear() tuỳ chỉnh để tạo hiệu ứng lò xo vượt quá giá trị mục tiêu trước khi ổn định.

.spring {
  /* Define the physics-based easing as a reusable variable */
  --spring-easing: linear(0, 0.016 0.5%, 0.06 1%, 0.226 2%, 1.116 5.4%, 1.375 6.6%, 1.527 7.7%, 1.565 8.2%, 1.585 8.8%, 1.581 9.3%, 1.559 9.8%, 1.458 10.9%, 0.937 14.3%, 0.784 15.5%, 0.693 16.6%, 0.67 17.1%, 0.657 17.7%, 0.671 18.7%, 0.729 19.8%, 1.042 23.3%, 1.13 24.5%, 1.182 25.6%, 1.201 26.7%, 1.192 27.7%, 1.156 28.8%, 0.977 32.2%, 0.925 33.4%, 0.894 34.5%, 0.882 35.6%, 0.887 36.6%, 0.907 37.7%, 1.045 42.4%, 1.069 44.5%, 1.059 46.3%, 0.979 50.9%, 0.96 53.4%, 0.966 55.3%, 1.013 59.9%, 1.024 62.3%, 0.986 71.2%, 1.008 79.9%, 0.995 88.9%, 1);


  /* Apply the easing with a duration that fits the spring's complexity */
  /* MANDATORY: Always include a duration; linear() does not calculate it automatically */
  transition: scale 0.8s var(--spring-easing);
}

.spring:hover {
  scale: 1.2;
}

Ví dụ: Hiệu ứng nảy

Ví dụ này cho thấy cách sử dụng hàm linear() tuỳ chỉnh để tạo hiệu ứng nảy.

.bounce {
  /* Define the physics-based easing as a reusable variable */
  --bounce-easing: linear(0, 0.214 14.7%, 0.386 23.7%, 0.598 31.9%, 0.999 44.7%, 0.807 52.6%, 0.762 56%, 0.747 59.4%, 0.758 62.4%, 0.793 65.6%, 0.999 77.4%, 0.961 81.2%, 0.949 84.8%, 0.956 88%, 0.993 95.5%, 1);


  /* Apply the easing with a duration that fits the bounce's complexity */
  /* MANDATORY: Always include a duration; linear() does not calculate it automatically */
  transition: scale 0.4s var(--bounce-easing);
}

.bounce:hover {
  scale: 1.2;
}

Những điểm chính cần xem xét

  • Hiệu suất: Để có ảnh động dựa trên kiến thức vật lý mượt mà nhất, hãy áp dụng linear() cho các thuộc tính chạy trên một luồng riêng biệt, chẳng hạn như transform và opacity.
  • Độ chính xác so với tải trọng: Mặc dù nhiều điểm dừng hơn sẽ giúp đường cong mượt mà hơn, nhưng cũng làm tăng kích thước của CSS. Hầu hết các trình tạo đều cho phép bạn "đơn giản hoá" đường cong để tìm ra sự cân bằng tối ưu giữa độ mượt và kích thước mã.
  • Tránh sử dụng độ mờ cho hiệu ứng nảy: Việc áp dụng hiệu ứng nảy cho opacity có thể gây ra hiện tượng nhấp nháy gây khó chịu nếu giá trị vượt quá 0 hoặc 1.
  • Hỗ trợ tiếp cận: Ảnh động phức tạp dựa trên vật lý có thể gây mất tập trung hoặc gây nhạy cảm với chuyển động cho một số người dùng. Luôn tôn trọng lựa chọn ưu tiên của người dùng bằng cách giảm hoặc tắt các ảnh động này.
@media (prefers-reduced-motion: reduce) {
  .element {
    transition: none;
  }
}

Chiến lược dự phòng

Dự phòng CSS

Đối với các trình duyệt không hỗ trợ linear(), hãy cung cấp một hàm easing chuẩn làm phương án dự phòng. Trình duyệt sẽ bỏ qua giá trị linear() nếu không nhận ra giá trị đó, quay lại khai báo hợp lệ trước đó.

.element {
  /* Fallback for older browsers (standard smooth exit) */
  transition: transform 0.8s ease-out;
  
  /* Modern browsers will override with the physics-based easing */
  transition-timing-function: linear(0, 1.1, 0.95, 1.02, 1);
}

Dự phòng thư viện JavaScript (Motion/GSAP)

Không bắt buộc: Nếu ảnh động vật lý có độ chân thực cao là yếu tố quan trọng ngay cả trong các trình duyệt cũ, hãy sử dụng thư viện JavaScript như Motion (motion.dev) hoặc GSAP (greensock.com) để xử lý ảnh động khi linear() không được hỗ trợ.

  1. Phát hiện tính năng hỗ trợ: Sử dụng CSS.supports() để kiểm tra xem trình duyệt có xử lý hàm linear() hay không.
  2. Tải/áp dụng có điều kiện: Nếu không được hỗ trợ, hãy sử dụng phương thức triển khai hiệu ứng lò xo hoặc nảy của thư viện.
/* Detect if the browser supports the linear() function */
const supportsLinearEasing = window.CSS && CSS.supports('animation-timing-function', 'linear(0, 1)');

if (!supportsLinearEasing) {
  /* 
     Example using Motion (motion.dev) for a spring fallback.
     This should only be initialized if native CSS support is missing.
  */
  import("https://cdn.jsdelivr.net/npm/motion@latest/dist/motion.js").then(({ animate, spring }) => {
    animate(".element", { transform: "scale(1.2)" }, {
      easing: spring({ stiffness: 100, damping: 10 })
    });
  });
}

Bạn cũng có thể sử dụng @supports trong CSS để phát hiện tính năng rõ ràng hơn:

@supports not (animation-timing-function: linear(0, 1)) {
  .element {
    /* Alternative experience for unsupported browsers */
    transition-duration: 0.4s;
    transition-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1);
  }
}