가이드 · 07
React Native에서 옮겨 오기 무엇이 그대로이고, 무엇이 다르고, 웹이 무엇을 더하는지.
같은 호출 컨트롤러, 그래프, 설정은 React Native의 Animated를 따릅니다. React Native가 Animated.View를 렌더하는 곳에 Animated.div 같은 DOM 호스트를 렌더하세요. useAnimatedValue도 React Native처럼 쓸 수 있습니다.
JavaScript가 꺼져 있습니다. 아래 코드가 예제의 전체 소스입니다.
App.jsx import { useEffect } from 'react' ;
import { Animated , Easing , useAnimatedValue } from '@kkwaenggwari/animated' ;
import './styles.css' ;
export default function App ({ duration = 1200 } ) {
const spin = useAnimatedValue (0 );
const pulse = useAnimatedValue (0 );
const scrollY = useAnimatedValue (0 );
useEffect (() => {
const animation = Animated .parallel ([
Animated .loop (
Animated .timing (spin, {
toValue : 1 ,
duration,
easing : Easing .linear ,
useNativeDriver : true ,
}),
),
Animated .loop (
Animated .sequence ([
Animated .timing (pulse, { toValue : 1 , duration : duration / 2 , useNativeDriver : true }),
Animated .timing (pulse, { toValue : 0 , duration : duration / 2 , useNativeDriver : true }),
]),
),
]);
animation.start ();
return () => animation.stop ();
}, [duration]);
const rotate = spin.interpolate ({ inputRange : [0 , 1 ], outputRange : ['0deg' , '360deg' ] });
const scale = pulse.interpolate ({ inputRange : [0 , 1 ], outputRange : [1 , 1.25 ] });
const headerScale = scrollY.interpolate ({
inputRange : [0 , 120 ],
outputRange : [1 , 0.6 ],
extrapolate : 'clamp' ,
});
return (
<div className ="stage" >
<div className ="row" >
<Animated.div className ="spinner" style ={{ transform: [{ rotate }] }} />
<Animated.div className ="dot" style ={{ transform: [{ scale }] }} />
</div >
<div
className ="scroll"
onScroll ={Animated.event([{ nativeEvent: { contentOffset: { y: scrollY } } }], {
useNativeDriver: false ,
})}
>
<Animated.div className ="header" style ={{ transform: [{ scale: headerScale }] }}>
Scroll this list
</Animated.div >
{Array.from({ length: 12 }, (_, index) => (
<div key ={index} className ="item" >
Row {index + 1}
</div >
))}
</div >
</div >
);
}styles.css .stage {
display : grid;
gap : 18px ;
padding : 28px ;
}
.row {
display : flex;
align-items : center;
gap : 28px ;
}
.spinner {
width : 56px ;
height : 56px ;
border : 6px solid #eef2ff ;
border-top-color : #2854ff ;
border-radius : 50% ;
}
.dot {
width : 40px ;
height : 40px ;
border-radius : 50% ;
background : #5c7cff ;
}
.scroll {
height : 220px ;
max-width : 420px ;
border : 1px solid #e4e6ef ;
border-radius : 16px ;
overflow-y : auto;
}
.header {
position : sticky;
top : 0 ;
padding : 18px ;
background : #2854ff ;
color : #fff ;
font-weight : 700 ;
transform-origin : left top;
}
.item {
padding : 14px 18px ;
border-top : 1px solid #f0f1f7 ;
}알아 둘 차이 옮긴 코드가 기기에서와 같이 동작하도록 지키는 세부 사항입니다.
useNativeDriver와 isInteraction은 받아들입니다. 대신 재생 경로는 출력마다 정해집니다. 가능한 출력은 브라우저가, 나머지는 JavaScript가 재생합니다.spring은 stiffness/damping/mass, bounciness/speed, tension/friction을 받고, 아무것도 없으면 React Native 기본값입니다.interpolate는 easing과 세 가지 외삽 방식을 지원합니다.Easing은 elastic까지 React Native와 같습니다. Easing.exp는 정확히 0에서 시작하도록 0.1% 보정되어 브라우저 재생을 쓸 수 있습니다.decay 속도는 밀리초당, 스프링 속도는 초당 단위로 React Native와 같습니다. Animated.createAnimatedComponent는 ref를 전달하는 컴포넌트를 감쌉니다.Spinner.jsx 복사
<Animated .View style={{ transform : [{ rotate }] }} />
<Animated.div style ={{ transform: [{ rotate }] }} />
const spin = useAnimatedValue (0 );
const rotate = spin.interpolate ({ inputRange : [0 , 1 ], outputRange : ['0deg' , '360deg' ] });
Animated .loop (
Animated .timing (spin, { toValue : 1 , duration : 900 , easing : Easing .linear , useNativeDriver : true }),
).start ();웹이 더하는 것 평범한 React style이 훅 값을 바로 받고, seed/pose/respond가 목적지와 제스처를 설명하며, Animated.Keep과 Animated.Scene이 퇴장과 레이아웃을 맡습니다.