Динамика на основе физики

Веб-функции: linear() easing

Традиционные функции плавности CSS, такие как ease-in или cubic-bezier(), ограничены простыми кривыми, что делает невозможным создание сложных физических эффектов, таких как отскоки или пружины. Функция linear() позволяет решить эту проблему, задав ряд точек, которые могут аппроксимировать сложные кривые. Переходы и анимация интерполируются на основе прямых линий между остановками, но при достаточном количестве остановок они могут выглядеть плавными.

Руководство по настройке

  1. Создайте точки кривой. Вручную наносить десятки точек для пружины или отскока нецелесообразно. Используйте функцию синхронизации из внешней библиотеки или инструмент для преобразования существующей функции плавности JavaScript или пути SVG в синтаксис linear(). При желании вы можете сохранить эти функции как дополнительные параметры CSS, чтобы использовать их на всем сайте.
  2. Определите функцию времени. Примените сгенерированные точки к свойству transition-timing-function или animation-timing-function или через сокращения transition или animation.
  3. Настройте длительность. В отличие от физических движков JavaScript, где длительность определяется физическими свойствами (массой, жесткостью), в CSS по-прежнему требуется фиксированное значение duration. Возможно, вам потребуется скорректировать продолжительность, чтобы получить желаемый эффект.

Пример: "Весеннее облегчение".

В этом примере показано, как использовать пользовательскую функцию linear() для создания эффекта пружины, который превышает целевое значение перед установкой.

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

Пример: отскок

В этом примере показано, как использовать пользовательскую функцию linear() для создания эффекта отскока.

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

На что обратить внимание

  • Производительность. Чтобы анимация на основе физики была максимально плавной, применяйте linear() к свойствам, которые выполняются в отдельном потоке, например transform и opacity.
  • Точность и объем данных. Чем больше контрольных точек, тем плавнее кривая, но тем больше размер CSS-файла. Большинство генераторов позволяют упростить кривую, чтобы найти оптимальный баланс между плавностью и размером кода.
  • Не используйте прозрачность для отскоков. Применение отскоков к свойству opacity может привести к визуально неприятному мерцанию, если значение выходит за пределы диапазона от 0 до 1.
  • Специальные возможности. Сложные анимации, основанные на физике, могут отвлекать или вызывать чувствительность к движению у некоторых пользователей. Всегда учитывайте предпочтения пользователей, уменьшая или отключая эти анимации.
@media (prefers-reduced-motion: reduce) {
  .element {
    transition: none;
  }
}

Резервные стратегии

Резервный ССЦ

Для браузеров, которые не поддерживают linear(), укажите стандартную функцию плавности в качестве резервной. Браузер проигнорирует значение linear(), если оно не будет распознано, и вернется к предыдущему действительному объявлению.

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

Резервная библиотека JavaScript (Motion/GSAP)

Необязательно. Если вам нужна высокоточная физическая анимация даже в старых браузерах, используйте библиотеку JavaScript, например Motion (motion.dev) или GSAP (greensock.com), чтобы обрабатывать анимацию, когда linear() не поддерживается.

  1. Проверка поддержки. Используйте CSS.supports(), чтобы проверить, поддерживает ли браузер функцию linear().
  2. Условная загрузка или применение. Если функция не поддерживается, используйте реализацию пружины или отскока из библиотеки.
/* 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 })
    });
  });
}

Вы также можете использовать @supports в CSS для более явного обнаружения функций:

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