基于物理机制的缓动

Web 功能: linear() 缓动

传统的 CSS 缓动函数(例如 ease-in 或 cubic-bezier())仅限于简单曲线,因此无法创建复杂的基于物理的效果(例如弹跳或弹簧)。linear() 时间函数通过允许您提供一系列可近似复杂曲线的停靠点来解决此问题。过渡和动画是根据停靠点之间的直线进行插值的,但只要停靠点足够多,过渡和动画就会显得很平滑。

实施步骤

  1. 生成曲线停止点:手动绘制数十个点来实现弹簧或弹跳效果是不切实际的。使用外部库中的计时函数,或使用工具将现有 JavaScript 缓动函数或 SVG 路径转换为 linear() 语法。可选:将这些时间函数存储为 CSS 自定义属性,以便在整个网站中重复使用。
  2. 定义计时函数:将生成的停止点应用于 transition-timing-function 或 animation-timing-function 属性,或通过 transition 或 animation 简写形式应用。
  3. 调整时长: 与 JavaScript 物理引擎(时长由质量、刚度等物理属性决定)不同,CSS 仍需要固定的 duration。您可能需要调整时长才能达到预期效果。

示例:Spring Easing

此示例展示了如何使用自定义 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 的大小。大多数生成器都允许您“简化”曲线,以便在平滑度和代码大小之间找到最佳平衡点。
  • 避免对不透明度使用弹跳效果:如果值超出 0 以下或 1 以上,对 opacity 应用弹跳缓动效果可能会导致视觉上不协调的闪烁。
  • 无障碍功能:复杂的基于物理特性的动画可能会分散某些用户的注意力,或导致其产生运动敏感性。始终尊重用户偏好,减少或停用这些动画。
@media (prefers-reduced-motion: reduce) {
  .element {
    transition: none;
  }
}

后备策略

CSS 后备

对于不支持 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)

可选:如果即使在旧版浏览器中,高保真物理动画也至关重要,请使用 Motion (motion.dev) 或 GSAP (greensock.com) 等 JavaScript 库在不支持 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 })
    });
  });
}

您还可以在 CSS 中使用 @supports 进行更明确的功能检测:

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