指南 · 03
Animated 元件
渲染一般元素,讓它們移動到目的地、回應手勢並優雅地離場。
Animated.<tag>
Animated.div、Animated.button、Animated.svg 以及其他所有 HTML 或 SVG 標籤,都會渲染沒有包裝層的一般元素。它們的 style 接受值,transform 可以像 React Native 一樣寫成陣列。
這些元素上有限的 transform 與 opacity 動態(包括彈簧)可以由瀏覽器播放。
seed、pose、poses 與 tempo
seed 是第一格,pose 是目前的目的地(一個物件,或 poses 中某一項的名稱),tempo 是時間曲線或彈簧。只改 tempo 不會重播沒有改變的目的地。
元素抵達時會觸發 onRest。
Card.jsx<Animated.article
seed={{ opacity: 0, transform: [{ translateY: 16 }] }}
pose={selected ? 'raised' : 'rest'}
poses={{
rest: { opacity: 1, transform: [{ translateY: 0 }, { scale: 1 }] },
raised: { opacity: 1, transform: [{ translateY: -8 }, { scale: 1.04 }] },
}}
tempo={{ spring: { stiffness: 300, damping: 26 } }}
onRest={() => console.log('arrived')}
/>;
回應手勢
respond 把手勢對應到暫時的目的地:hover、focus、focusWithin、press、longPress、drag、inView 等。回應結束時,元素會從當下所在的位置回到自己的 pose。
onResponse 會回報每個邊緣;respond={{ press: {} }} 只觀察手勢,不改變任何視覺效果。
用 Animated.Scope 共用預設值
Animated.Scope 會把 pose 名稱、tempo 與動畫預設值傳給其內的 Animated 元素。
Menu.jsx<Animated.Scope tempo={{ spring: { stiffness: 380, damping: 30 } }}>
<Animated.li pose={{ opacity: 1 }} />
<Animated.li pose={{ opacity: 1 }} />
</Animated.Scope>;
你自己的元件
Animated.wrap(Component)(在 React Native 中是 createAnimatedComponent)能讓一個轉發 ref、最後解析為單一 DOM 元素的元件接受同樣的 props。
Link.jsximport { forwardRef } from 'react';
import { Animated } from '@kkwaenggwari/animated';
const Link = forwardRef((props, ref) => <a ref={ref} {...props} />);
const AnimatedLink = Animated.wrap(Link);
<AnimatedLink href="/pricing" respond={{ hover: { transform: [{ translateX: 4 }] } }} />;