飞行中重定向:animateTo 不丢速度地改目标
引擎的值源不止「关键帧加缓动」一种。new Animation({ spring: { stiffness, damping, from, to, velocity } }) 给出原生弹簧值源:值由物理弹簧实时产出,时长由 settleTime 反推而非给定。
它最关键的能力是 animateTo(newTarget)——在动画飞行途中改目标时,以当前显示值与当前速度为新初始条件重建弹簧。中断与重定向那页手搓的那套接管逻辑,在本页收成了一等 API。
1 · 谁能带着速度拐弯
点任一条轨道,两个球同时把那一点设为新目标。趁球还在飞时连点不同位置,差别立刻可见。
上轨用 animateTo,带着当前速度平滑拐向新目标;下轨用 keyframe 重启——取消旧动画、从当前位置新起一条 easeOut——每次都把速度清零,看得出「一顿」。
2 · 为什么固定曲线做不到
animateTo 复用同一条 Animation:读出打断时刻的 value 与 velocity,以二者为新弹簧的 from 与 velocity 重建,朝新 to 演化。位置与速度都连续。
固定曲线值源只能 cancel 旧动画再起一条,而新曲线的起始速度由缓动写死——easeOut 的起点速度是该段平均速度的两倍,与打断时的真实速度毫无关系。位置仍连续(都从当前点出发),速度却在衔接处跳变。
注 · 读数里蓝球那一栏记的是「重启时的速度」,不是重启后的速度——它取自被 cancel 的那条动画在最后一刻的 velocity,正是被丢掉的那个值。数值越大,那一顿就越明显;从静止开始的第一次点击它是 0,此时两条轨道看不出差别。
import { Animation } from '@vega/anim';
// 原生弹簧值源: 值由物理弹簧实时产出, 时长由 settleTime 反推
const anim = new Animation({
spring: { stiffness: 180, damping: 16, from: pos, to: target, velocity: 0 },
onUpdate: (v) => place(v),
});
// 飞行途中改目标: 以当前 value + velocity 为新初始条件, 速度连续
anim.animateTo(newTarget); // 不丢速度地拐向新目标
anim.animateTo(target, { from, velocity }); // 手势释放: 喂入落点与手势速度
// 对照: keyframe 只能 cancel 旧的再起一条 → 起始速度由缓动决定, 衔接丢速度
old?.cancel();
const restart = new Animation({ keyframes: [pos, target], ease: 'easeOut' });
手势释放时把拖拽落点与手势速度一起喂给 animateTo(target, { from, velocity }),就是 手势与 drag() 的惯性抛掷。弹簧本身的三种形态见弹簧,同一件事的手写版与它的取舍见中断与重定向。