Wygładzanie oparte na fizyce

Funkcje internetowe: linear() easing

Tradycyjne funkcje łagodzenia CSS, takie jak ease-in lub cubic-bezier(), są ograniczone do prostych krzywych, co uniemożliwia tworzenie złożonych efektów opartych na fizyce, takich jak odbicia czy sprężyny. Funkcja czasu linear() rozwiązuje ten problem, umożliwiając podanie serii punktów, które mogą przybliżać złożone krzywe. Przejścia i animacje są interpolowane na podstawie linii prostych między przystankami, ale przy wystarczającej liczbie przystanków mogą wydawać się płynne.

Etapy wdrażania

  1. Wygeneruj punkty krzywej: ręczne wykreślanie dziesiątek punktów dla efektu sprężyny lub odbicia jest niepraktyczne. Użyj funkcji czasu z biblioteki zewnętrznej lub narzędzia do konwersji istniejącej funkcji wygładzania JavaScriptu lub ścieżki SVG na składnię linear(). Opcjonalnie: zapisz te funkcje czasu jako właściwości niestandardowe CSS, aby móc ich używać w całej witrynie.
  2. Zdefiniuj funkcję czasu: zastosuj wygenerowane punkty do właściwości transition-timing-function lub animation-timing-function albo za pomocą skrótów transition lub animation.
  3. Dostosuj czas trwania: W odróżnieniu od silników fizyki JavaScriptu, w których czas trwania jest określany na podstawie właściwości fizycznych (masy, sztywności), CSS nadal wymaga stałej wartości duration. Aby uzyskać zamierzony efekt, konieczne może być dostosowanie czasu trwania.

Przykład: Spring Easing

Ten przykład pokazuje, jak za pomocą niestandardowej funkcji linear() utworzyć efekt sprężyny, który przekracza wartość docelową, zanim się ustabilizuje.

.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;
}

Przykład: Bounce Easing

Ten przykład pokazuje, jak za pomocą niestandardowej funkcji linear() utworzyć efekt odbicia.

.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;
}

najważniejsze kwestie

  • Wydajność: aby uzyskać jak najpłynniejsze animacje oparte na fizyce, zastosuj linear() do właściwości, które działają w osobnym wątku, takich jak transform i opacity.
  • Precyzja a rozmiar: większa liczba punktów pozwala uzyskać gładszą krzywą, ale zwiększa też rozmiar kodu CSS. Większość generatorów pozwala „uprościć” krzywą, aby znaleźć optymalną równowagę między płynnością a rozmiarem kodu.
  • Unikaj stosowania efektu odbicia do właściwości Opacity: zastosowanie efektu odbicia do właściwości opacity może spowodować wizualnie nieprzyjemne migotanie, jeśli wartość przekroczy zakres od 0 do 1.
  • Ułatwienia dostępu: złożone animacje oparte na fizyce mogą rozpraszać niektórych użytkowników lub powodować u nich nadwrażliwość na ruch. Zawsze szanuj preferencje użytkowników, ograniczając lub wyłączając te animacje.
@media (prefers-reduced-motion: reduce) {
  .element {
    transition: none;
  }
}

Strategie zastępcze

CSS Fallback

W przypadku przeglądarek, które nie obsługują funkcji linear(), podaj standardową funkcję wygładzania jako zastępczą. Jeśli przeglądarka nie rozpozna wartości linear(), zignoruje ją i użyje poprzedniej prawidłowej deklaracji.

.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);
}

Zastępcza biblioteka JavaScript (Motion/GSAP)

Opcjonalnie: jeśli wysokiej jakości animacja fizyczna jest kluczowa nawet w starszych przeglądarkach, użyj biblioteki JavaScript, takiej jak Motion (motion.dev) lub GSAP (greensock.com), aby obsłużyć animację, gdy właściwość linear() nie jest obsługiwana.

  1. Wykrywanie obsługi: użyj CSS.supports(), aby sprawdzić, czy przeglądarka obsługuje funkcję linear().
  2. Warunkowe wczytywanie/stosowanie: jeśli nie jest obsługiwane, użyj implementacji sprężyny lub odbicia biblioteki.
/* 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 })
    });
  });
}

Możesz też użyć @supports w CSS, aby uzyskać bardziej precyzyjne wykrywanie funkcji:

@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);
  }
}