الأدلة · 06
الخطوط الزمنية شغّل مسارات كثيرة من ساعة واحدة قابلة للتنقل: تشغيل وإيقاف مؤقت وتنقل وعكس وتغيير السرعة.
مسارات على ساعة واحدة ينشئ useTimeline(tracks, options, deps) خطًا زمنيًا يملكه المكوّن. كل مسار قائمة إطارات مفتاحية، أو { values, times, at, duration } حيث at وduration بالمللي ثانية.
progress متغيّر CSS واحد، والمسارات الرقمية ومسارات الأطوال تعبيرات calc() منه، فيكتب الخط الزمني في style العادي متغيّرًا واحدًا لكل إطار.
JavaScript معطّل. الشيفرة أدناه هي المثال الكامل.
App.jsx import { useRef } from 'react' ;
import { useTimeline } from '@kkwaenggwari/animated' ;
import './styles.css' ;
export default function App ({ duration = 3000 , repeat = true } ) {
const timeline = useTimeline (
{
x : ['0px' , '220px' , '220px' , '0px' , '0px' ],
y : ['0px' , '0px' , '110px' , '110px' , '0px' ],
turn : ['0deg' , '90deg' , '180deg' , '270deg' , '360deg' ],
round : ['50%' , '12%' , '50%' , '12%' , '50%' ],
},
{ duration, repeat : repeat ? Infinity : 0 },
[duration, repeat],
);
const bar = useRef (null );
const seek = (event ) => {
const box = bar.current .getBoundingClientRect ();
const ratio = Math .min (1 , Math .max (0 , (event.clientX - box.left ) / box.width ));
timeline.pause ();
timeline.seek (ratio * timeline.duration );
};
const { x, y, turn, round } = timeline.values ;
return (
<div className ="stage" >
<div className ="canvas" >
<span
className ="shape"
style ={{ transform: `translate (${x }, ${y }) rotate (${turn })`, borderRadius: round }}
/>
</div >
<div className ="player" >
<button type ="button" onClick ={() => timeline.play()}>
Play
</button >
<button type ="button" onClick ={() => timeline.pause()}>
Pause
</button >
<div
ref ={bar}
className ="scrub"
onPointerDown ={(event) => {
event.currentTarget.setPointerCapture(event.pointerId);
seek(event);
}}
onPointerMove={(event) => {
if (event.buttons) seek(event);
}}
>
<span style ={{ transform: `scaleX (${timeline.progress })` }} />
</div >
</div >
</div >
);
}styles.css .stage {
display : grid;
gap : 16px ;
padding : 28px ;
}
.canvas {
height : 190px ;
padding : 20px ;
border-radius : 16px ;
background : #0b1440 ;
}
.shape {
display : block;
width : 60px ;
height : 60px ;
background : #5c7cff ;
}
.player {
display : flex;
align-items : center;
gap : 8px ;
}
.player button {
min-height : 40px ;
padding : 0 16px ;
border : 1px solid #e4e6ef ;
border-radius : 999px ;
background : #fff ;
font : inherit;
cursor : pointer;
}
.scrub {
flex : 1 ;
height : 12px ;
border-radius : 999px ;
background : #eef2ff ;
overflow : hidden;
cursor : pointer;
touch-action : none;
}
.scrub span {
display : block;
height : 100% ;
background : #2854ff ;
transform-origin : left center;
}التحكم في التشغيل تتحكم play({ from, rate }) وpause() وseek(ms) وreverse() في الساعة. وتصفها state وcurrentTime وduration والوعد finished. ويكرّرها repeat وrepeatDelay.
Title.jsx نسخ الشيفرة const intro = useTimeline (
{
y : ['24px' , '0px' ],
fade : { values : [0 , 1 ], at : 0 , duration : 300 },
line : { values : [0 , 1 ], at : 200 , duration : 600 },
},
{ duration : 800 },
);
intro.seek (400 );
intro.play ({ rate : 0.5 });
intro.reverse ();خارج React createTimeline هي الساعة نفسها من دون مكوّن. استدعِ dispose() حين تنتهي.