跨端统一的 Spring 动画参数协议:Web 与 Flutter 共享物理配置

封面信息图

在多端协同开发的大型项目中,最容易被各端工程师“各执一词”的莫过于交互动效。Web 端工程师习惯在 CSS 里写 cubic-bezier(0.25, 0.1, 0.25, 1),Flutter 端工程师在代码里随手调了一个 Curves.easeOutBack,而 iOS 原生端工程师则直接调用了 SwiftUI 的 .spring(response: 0.3, dampingFraction: 0.7)

结果就是:同一个 App 在不同平台打开时,抽屉弹出的弹跳感、卡片悬浮的沉降感完全是三种截然不同的手感,严重割裂了产品的统一品牌认知。

为了实现跨平台“一次调参,全端物理对齐”,我们设计了一套基于纯物理特征(Mass, Stiffness, Damping)的通用 Spring 动画参数协议(Universal Spring Protocol),并在 Web 与 Flutter 两端分别构建了高精度的解析与消费引擎。

通用物理弹簧协议的 JSON Schema

跨端协议严禁使用任何平台私有的时间或曲线枚举,必须基于经典力学的三个核心物理量:

  • mass(质量 $m$):物体的物理惯性,默认 1.0
  • stiffness(刚度 $k$):弹簧恢复力的强弱,取值通常在 50 ~ 500
  • damping(阻尼 $c$):阻止振荡的阻尼消耗,取值通常在 10 ~ 50
  • velocity(可选初速度 $v_0$):手势释放时的瞬时速度。
/* tokens/motion/spring-tokens.json */
{
  "$schema": "https://design-system.internal/motion-spring.schema.json",
  "springPresets": {
    "snappyBrisk": {
      "mass": 1.0,
      "stiffness": 300.0,
      "damping": 22.0,
      "description": "轻快利落的微交互反馈 (微弹,无拖沓)"
    },
    "gentleFloat": {
      "mass": 1.2,
      "stiffness": 140.0,
      "damping": 18.0,
      "description": "柔和的大画幅模态框入场"
    },
    "heavyMagnetic": {
      "mass": 2.2,
      "stiffness": 180.0,
      "damping": 38.0,
      "description": "厚重电吸门质感 (过阻尼,零反弹)"
    }
  }
}

Flutter 消费端:直接映射 SpringSimulation

在 Flutter 中,官方动画库原生支持基于物理特性的弹簧模拟器 SpringSimulation。我们只需将协议 JSON 中的参数映射为 SpringDescription

// flutter_spring_bridge.dart
import 'package:flutter/physics.dart';
import 'package:flutter/material.dart';

class UniversalSpringBridge {
  static SpringDescription createSpringDescription({
    required double mass,
    required double stiffness,
    required double damping,
  }) {
    return SpringDescription(
      mass: mass,
      stiffness: stiffness,
      damping: damping,
    );
  }

  // 启动物理弹簧模拟
  static void runSpringAnimation({
    required AnimationController controller,
    required double from,
    required double to,
    required SpringDescription spring,
    double initialVelocity = 0.0,
  }) {
    final simulation = SpringSimulation(
      spring,
      from,
      to,
      initialVelocity,
    );
    controller.animateWith(simulation);
  }
}

在 Flutter 组件中使用时极其简洁:

// 消费 snappyBrisk 预设
final springConfig = UniversalSpringBridge.createSpringDescription(
  mass: 1.0,
  stiffness: 300.0,
  damping: 22.0,
);

UniversalSpringBridge.runSpringAnimation(
  controller: _controller,
  from: 0.0,
  to: 1.0,
  spring: springConfig,
);

Web 消费端:编译为纯 CSS linear() 零开销执行

在 Web 端,为了避免使用重量级的 JS 物理仿真库(如 Framer Motion)霸占主线程,我们在构建阶段利用我们在前文推导的微分方程求解器,将 JSON 中的物理参数静态编译为完全等价的 CSS linear() 缓动序列

// web-spring-compiler.ts
import { evaluateSpringPosition } from './spring-physics-solver';

export function compileSpringToCssLinear(
  mass: number,
  stiffness: number,
  damping: number,
  samples: number = 40
): { cssLinear: string; estimatedDurationMs: number } {
  const omega0 = Math.sqrt(stiffness / mass);
  const zeta = damping / (2 * Math.sqrt(stiffness * mass));
  
  // 估算振荡收敛到 99.5% 阈值所需的物理总时长
  const duration = Math.min(1.5, Math.max(0.2, (4.5 / (zeta * omega0))));
  const durationMs = Math.round(duration * 1000);

  const values: string[] = [];
  for (let i = 0; i <= samples; i++) {
    const t = (i / samples) * duration;
    const pos = evaluateSpringPosition({ mass, stiffness, damping }, t);
    const progressPercent = ((i / samples) * 100).toFixed(1);
    values.push(`${pos.toFixed(3)} ${progressPercent}%`);
  }

  return {
    cssLinear: `linear(${values.join(', ')})`,
    estimatedDurationMs: durationMs,
  };
}

编译输出的 CSS 变量直接供 Web 样式表全局引用:

/* 自动编译生成的 Web 端动效产物 */
:root {
  --spring-snappy-duration: 480ms;
  --spring-snappy-easing: linear(
    0 0.0%, 0.045 2.5%, 0.178 5.0%, 0.582 12.5%, 0.892 20.0%,
    1.034 27.5%, 1.052 32.5%, 1.021 40.0%, 0.995 47.5%, 1 100.0%
  );
}

.interactive-popup-web {
  transition: transform var(--spring-snappy-duration) var(--spring-snappy-easing);
}

总结

通过建立“物理参数为真源(Single Source of Physics)”的跨端协议,我们彻底打破了 Web 与 Flutter 在动效实现上的生态壁垒。设计师只需在设计系统中调节一组质感自洽的刚度与阻尼,几秒钟后,Web 端的 GPU 合成器与 Flutter 的自绘制管线便能在数千台不同尺寸的设备上,同步呈现出完全同一质感的物理节拍。

Logo

一站式 AI 云服务平台

更多推荐