Reactでanime.jsを使ってみる
こんにちは🤠
iOSエンジニアのmuukiiです🤠
最近は業務でReactを少し触ることがあるのですが、まだまだ理解していないことが多くて苦戦中です😵
学習中なので、そのメモとして記事を書こうと思います。
今回はReactとanime.jsの連携についての話をします。
anime.jsについては下記リンクを参照してください。
anime.jsの使い方は次のような雰囲気です。
anime({
targets: '#cssSelector .el',
translateX: 250
});
targetsにはCSS Selector
もしくはJavaScriptで取得したDOM Node
を指定することができます。配列で与えることも可能です。
上記の例はCSS Selector
を指定する例でしたが、DOM Node
を指定する例は次のようになります。
const el = document.querySelector('#domNode .el');
const domNode = anime({
targets: el,
translateX: 250
});
ReactのComponentやElementにアニメーションを指定する
CSS Selector
を使ってアニメーションを行う場合は問題なく実現はできますが、特定のComponentやElementにアニメーションを指定したい場合はrenderされた実際のDOM Node
を取得する必要があります。
Componentが持つDOM Node
を取得するにはRefsを使用します。
次のように記述することでMyComponent
がマウントされたタイミングでdiv
がアニメーションを開始します。
import * as React from 'react'
import anime from 'animejs'class MyComponent extends React.Component {
render() {
return (
<div
ref={ref => {
anime({
targets: ref,
translateX: 250,
})
}}
/>
)
}
}
マウントされる以外のタイミングでアニメーションを実行したい場合はref
をMyComponent
内で保持しておくことで実現できます。
Refsの扱いには注意が必要
Refsは場合によって返却されるものが異なります。先ほどの例で使用しているdiv
はelementに相当するものなのでrefの実体はDOM Node
になります。
しかし、ComponentやHOCではrefの挙動は異なります。
class Box extends React.Component {
render() {
return <div>box</div>
}
}class Container extends React.Component {
render(){
return <Box ref={ ref => { console.log(ref) }}>foo</Box>
}
}
この例ではrefはBox-Component自体を指すのでDOM Node
ではありません。
この場合は、ReactDOMを使ってrefを元にDOM Node
を取得します。
class Box extends React.Component {
render() {
return <div>box</div>
}
}
class Container extends React.Component {
render() {
return (
<Box
ref={ref => {
const dom = ReactDOM.findDOMNode(ref)
anime({
targets: dom,
translateX: 250,
})
}}
>
foo
</Box>
)
}
}
これでComponentの場合もアニメーションが可能になります。
このRefsの挙動の違いにはstyled-componentsで定義したComponentにアニメーションを適用しようとした時に気づいて調べていたのですが、styled-componentsの場合はinnerRef
というプロパティが実装されており、こちらを使用することで直接DOM Node
を受け取ることが可能でした。
HOCの場合はrefをもらうことができない様子。(まだ詳しく調べてないです。)
おわりに
anime.jsをReactで使用するためにreact-animeというライブラリが公開されていますが、Reactを使用しながらDOMとの連携を行う方法を知っておきたかったので今回のようなアプローチについて書きました。