指南 · 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。