गाइड · 05
प्रवेश, प्रस्थान और लेआउट जाते हुए children को उनकी गति ख़त्म होने तक रखें, और स्थिति व आकार के बदलाव एनिमेट करें, कंपोनेंट के पार भी।
Animated.Keep Animated.Keep key वाले सीधे children को उनके depart pose तक रखता है। seed={false} पहले रेंडर में मौजूद children को उनके pose से शुरू कराता है, wait प्रस्थान पूरे होने तक आने वाले children को रोकता है, और onDeparted आख़िरी के बाद चलता है।
JavaScript बंद है। नीचे का कोड पूरा उदाहरण है।
App.jsx import { useState } from 'react' ;
import { Animated } from '@kkwaenggwari/animated' ;
import './styles.css' ;
const departures = {
up : { opacity : 0 , transform : [{ translateY : -24 }] },
side : { opacity : 0 , transform : [{ translateX : 120 }] },
shrink : { opacity : 0 , transform : [{ scale : 0.6 }] },
};
let next = 4 ;
export default function App ({ depart = 'side' , wait = false } ) {
const [items, setItems] = useState ([1 , 2 , 3 ]);
const add = ( ) => setItems ((list ) => [...list, next++]);
const remove = (id ) => setItems ((list ) => list.filter ((item ) => item !== id));
return (
<Animated.Scene tempo ={{ spring: { stiffness: 320 , damping: 30 } }}>
<div className ="stage" >
<button type ="button" className ="add" onClick ={add} >
Add message
</button >
<Animated.Keep wait ={wait} >
{items.map((id) => (
<Animated.div
key ={id}
move
className ="message"
seed ={{ opacity: 0 , transform: [{ translateY: 16 }] }}
pose ={{ opacity: 1 , transform: [{ translateY: 0 }] }}
depart ={departures[depart]}
tempo ={{ spring: { stiffness: 320 , damping: 26 } }}
>
<span > Message #{id}</span >
<button type ="button" onClick ={() => remove(id)}>
Dismiss
</button >
</Animated.div >
))}
</Animated.Keep >
</div >
</Animated.Scene >
);
}styles.css .stage {
display : grid;
align-content : start;
gap : 10px ;
min-height : 320px ;
max-width : 420px ;
padding : 28px ;
}
button {
font : inherit;
cursor : pointer;
}
.add {
justify-self : start;
min-height : 44px ;
margin-bottom : 8px ;
padding : 0 20px ;
border : 0 ;
border-radius : 999px ;
background : #2854ff ;
color : #fff ;
font-weight : 650 ;
}
.message {
display : flex;
align-items : center;
justify-content : space-between;
gap : 12px ;
padding : 10px 10px 10px 18px ;
border : 1px solid #e4e6ef ;
border-radius : 14px ;
background : #fff ;
}
.message button {
min-height : 36px ;
padding : 0 14px ;
border : 1px solid #e4e6ef ;
border-radius : 999px ;
background : #f5f6fb ;
color : #16181d ;
}Animated.Scene और move Animated.Scene commit हुआ लेआउट मापता है। move वाला एलिमेंट अपनी स्थिति और आकार के बदलाव एनिमेट करता है; move="pill" जैसी स्ट्रिंग Scene के भीतर एक ही पहचान वाले एलिमेंट को जोड़ती है, तब भी जब एक अनमाउंट हो और दूसरा माउंट।
Scene उन एलिमेंट के लेआउट translate और scale का मालिक है, इसलिए अपने transform किसी भीतरी एलिमेंट पर रखें।
JavaScript बंद है। नीचे का कोड पूरा उदाहरण है।
App.jsx import { useState } from 'react' ;
import { Animated } from '@kkwaenggwari/animated' ;
import './styles.css' ;
const tabs = ['All' , 'Motion' , 'Layout' , 'Input' ];
const colors = ['#2854ff' , '#8fb0ff' , '#5c7cff' , '#16181d' , '#4a6bff' , '#7d9bff' ];
export default function App ({ columns = 3 , stiffness = 300 , damping = 28 } ) {
const [tab, setTab] = useState ('All' );
const [tiles, setTiles] = useState (colors);
const shuffle = ( ) => setTiles ((list ) => [...list.slice (1 ), list[0 ]]);
return (
<Animated.Scene tempo ={{ spring: { stiffness , damping } }}>
<div className ="stage" >
<nav className ="tabs" >
{tabs.map((name) => (
<button key ={name} type ="button" onClick ={() => setTab(name)}>
{name === tab && <Animated.span className ="pill" move ="pill" /> }
<span className ="label" > {name}</span >
</button >
))}
</nav >
<div className ="tiles" style ={{ gridTemplateColumns: `repeat (${columns }, 1fr )` }}>
{tiles.map((color) => (
<Animated.div key ={color} move className ="tile" style ={{ background: color }} />
))}
</div >
<button type ="button" className ="shuffle" onClick ={shuffle} >
Rotate tiles
</button >
</div >
</Animated.Scene >
);
}styles.css .stage {
display : grid;
gap : 18px ;
padding : 28px ;
}
button {
font : inherit;
cursor : pointer;
}
.tabs {
display : flex;
flex-wrap : wrap;
gap : 4px ;
justify-self : start;
padding : 4px ;
border-radius : 999px ;
background : #f5f6fb ;
}
.tabs button {
position : relative;
min-height : 40px ;
padding : 0 18px ;
border : 0 ;
background : none;
color : #16181d ;
}
.pill {
position : absolute;
inset : 0 ;
border-radius : 999px ;
background : #2854ff ;
}
.label {
position : relative;
}
.tabs button :has (.pill ) .label {
color : #fff ;
}
.tiles {
display : grid;
gap : 10px ;
max-width : 420px ;
}
.tile {
height : 64px ;
border-radius : 14px ;
}
.shuffle {
justify-self : start;
min-height : 44px ;
padding : 0 20px ;
border : 1px solid #e4e6ef ;
border-radius : 999px ;
background : #fff ;
}हुक से उपस्थिति जब आप माउंटिंग ख़ुद नियंत्रित करना पसंद करें, तब useAnimatedPresence(visible, { enter, exit }) { mounted, animatedValue } लौटाता है।
Toast.jsx कोड कॉपी करें const { mounted, animatedValue } = useAnimatedPresence (open, {
enter : (value ) => spring (value, { toValue : 1 }),
exit : (value ) => timing (value, { toValue : 0 , duration : 180 }),
});
return mounted ? <div style ={{ opacity: animatedValue }}> Saved</div > : null ;React के बाहर createLayoutScene वही कैप्चर/commit तालमेल किसी भी रेंडरर या हाथ से किए DOM बदलाव को देता है।
outside-react.js कोड कॉपी करें const scene = createLayoutScene ({ tempo : { spring : { stiffness : 320 , damping : 30 } } });
const card = scene.attach (element, { key : 'card' });
scene.capture ();
list.prepend (element);
scene.commit ();