指南 · 02
时序、弹簧与组合 选择驱动器、组合多个驱动器,并确切知道停止或替换时会发生什么。
timing、spring 和 decay timing 在固定的 duration 内沿曲线运动。spring 遵循物理规律,没有固定时长。decay 带着初速度开始,然后逐渐减速。
同样的驱动器接受数字、ValueXY 或记录,所以 { x, y, opacity } 可以一起移动。
JavaScript 已关闭。下面的代码就是完整的示例。
App.jsx import { Easing , parallel, spring, timing, useAnimatedValue } from '@kkwaenggwari/animated' ;
import './styles.css' ;
export default function App ({ stiffness = 180 , damping = 12 , mass = 1 , duration = 500 } ) {
const eased = useAnimatedValue (0 );
const standard = useAnimatedValue (0 );
const custom = useAnimatedValue (0 );
const go = ( ) => {
const toValue = custom.getValue () < 0.5 ? 1 : 0 ;
parallel ([
timing (eased, { toValue, duration, easing : Easing .inOut (Easing .cubic ) }),
spring (standard, { toValue }),
spring (custom, { toValue, stiffness, damping, mass }),
]).start ();
};
const lanes = [
['timing' , eased],
['spring()' , standard],
['spring(props)' , custom],
];
return (
<div className ="stage" >
<button type ="button" onClick ={go} >
Go
</button >
{lanes.map(([label, value]) => (
<div key ={label} className ="lane" >
<code > {label}</code >
<div className ="rail" >
<span
style ={{
left: `calc (${value } * (100 % - 40px ))`,
}}
/>
</div >
</div >
))}
</div >
);
}styles.css .stage {
display : grid;
gap : 14px ;
padding : 28px ;
}
button {
justify-self : start;
min-height : 44px ;
padding : 0 24px ;
border : 0 ;
border-radius : 999px ;
background : #2854ff ;
color : #fff ;
font : inherit;
font-weight : 650 ;
cursor : pointer;
}
.lane {
display : grid;
grid-template-columns : 120px 1 fr;
align-items : center;
gap : 12px ;
}
.lane code {
color : #1a33c7 ;
font-size : 13px ;
}
.rail {
position : relative;
height : 40px ;
border-radius : 999px ;
background : #f5f6fb ;
box-shadow : inset -2px 0 0 #e4e6ef ;
}
.rail span {
position : absolute;
top : 0 ;
width : 40px ;
height : 40px ;
border-radius : 50% ;
background : #8fb0ff ;
}
.lane :first-of-type .rail span {
background : #5c7cff ;
}
.lane :last-of-type .rail span {
background : #2854ff ;
}弹簧参数 只使用一种参数写法。都不指定时,使用 React Native 的默认弹簧(tension 40、friction 7)。弹簧的 velocity 默认取自被它打断的轨迹的速度。
springs.js 复制代码 spring (value, { toValue : 1 });
spring (value, { toValue : 1 , stiffness : 260 , damping : 20 });
spring (value, { toValue : 1 , bounciness : 8 , speed : 12 });
spring (value, { toValue : 1 , tension : 40 , friction : 7 }); 组合 sequence 依次运行,parallel 同时运行,stagger 按延迟依次启动,delay 等待,loop 重复。结果仍然是控制器,所以组合可以嵌套。
JavaScript 已关闭。下面的代码就是完整的示例。
App.jsx import {
delay,
loop,
parallel,
sequence,
spring,
stagger,
timing,
useAnimated,
} from '@kkwaenggwari/animated' ;
import './styles.css' ;
const keys = ['a' , 'b' , 'c' , 'd' , 'e' ];
export default function App ({ mode = 'stagger' , gap = 90 } ) {
const bars = useAnimated (
{ a : 0 , b : 0 , c : 0 , d : 0 , e : 0 },
(value ) => {
const group = (list ) =>
mode === 'sequence'
? sequence (list)
: mode === 'parallel'
? parallel (list)
: stagger (gap, list);
const rise = keys.map ((key ) =>
spring (value[key], { toValue : 1 , stiffness : 220 , damping : 16 }),
);
const fall = keys.map ((key ) => timing (value[key], { toValue : 0 , duration : 260 }));
loop (sequence ([group (rise), delay (500 ), group (fall), delay (300 )]));
},
[mode, gap],
);
return (
<div className ="stage" >
{keys.map((key) => (
<span key ={key} style ={{ transform: `scaleY (calc (0.15 + ${bars [key ]} * 0.85 ))` }} />
))}
</div >
);
}styles.css .stage {
display : flex;
align-items : flex-end;
justify-content : center;
gap : 14px ;
height : 260px ;
padding : 32px ;
}
.stage span {
width : 44px ;
height : 100% ;
border-radius : 12px ;
background : #2854ff ;
transform-origin : bottom;
}
.stage span :nth-child (2 n) {
background : #8fb0ff ;
}
.stage span :nth-child (3 ) {
background : #5c7cff ;
}start、stop 和 reset 每个控制器都有 start(callback?)、stop() 和 reset()。回调会收到 { finished }:动效被停止或替换时为 false。
在同一个值上启动新的驱动器,会从当前位置替换正在运行的那个,不会跳到任何一端。
controller.js 复制代码 const move = timing (value, { toValue : 1 , duration : 600 });
move.start (({ finished } ) => {
});
move.stop ();
move.reset (); 追随另一个值 动态的 toValue 会在那个值变化时重新启动驱动器,就像 React Native 中的跟踪。follow(target, source) 是同一种弹簧连接的具名函数形式。
tracking.js 复制代码
spring (badge, { toValue : pointer, stiffness : 300 , damping : 26 }).start ();
follow (badge, pointer, { stiffness : 300 , damping : 26 });缓动与关键帧 Easing 与 React Native 一致:linear、quad、cubic、sin、circle、exp、elastic、back、bounce、bezier,以及 in、out、inOut 辅助函数。keyframes(value, frames, options) 让一个值依次经过多个数字,可选 times 和 repeat。