React NativeのAnimated を試す
React Nativeのアニメーションのテスト。
Animated関連のAPIを使用するようで、この仕組みのイメージが少し分かった。
特定のカーブに従って何かしらの値を変化させて、 その変化をAnimatedなComponentで拾うという感じ。
変化させる値はAnimated.Value()
関数で作る。
percent = new Animated.Value(0);
この値を時間経過によって変化させる。これをアニメーションと言っていて、Animated.timing( ... ).start()
を使う。
startAnime = () => { Animated.timing(this.percent, { toValue: len, duration: 10*1000, useNativeDriver: true, easing: Easing.linear, }).start(); }
toValue
は最終的に持っていきたい値。
duration
はどれくらいの時間をかけて変化させるか。msec単位。
iOSの場合useNativeDriver:
指定は必須のようで、ないと怒られる。
true
にできない場合もあるので、そのときはfalse
で。
easing
は値を変化されるカーブを指定できるが、ここではリニアに設定。
あとは、アニメーションさせたい対象。 標準では、
- Animated.Image
- Anmated.ScrollView
- Animated.Text
- Animated.View
- Animated.FlatList
- Animated.SectionList
が用意されている。これらのComponentの任意のpropをアニメーション対象に指定できる、ということのようだ。
さて、ここではsvgライブラリを使ってCircleオブジェクトをアニメーション対象としたい。 この場合は、
const AnimatedCircle = Animated.createAnimatedComponent(Circle);
という風にすれば、Animated 対象となる。
単なるCircle
を使ってもだめだった。
Animated.Value
の変化を観察してくれない(つまり、動かない)。
最初は、Animated.Xxx
がなぜ必要か分からなかったが、値の変化を拾ってくるかどうか、ということね。
逆に言えば、Animated.createAnimatedComponent()
を使えてば、なんでもAnimated対象になるのなら、最強な気がする。
ここではCircle
の
strokeDashoffset={this.percent}
というpropがAnimated.Value
を使っている。この値の変化を観察してくれるというわけだ。
以下、全コード。
import React, { Component } from 'react'; import { SafeAreaView, StyleSheet, Button, Animated, Easing, } from 'react-native'; import Svg, { Circle } from 'react-native-svg'; const RADIUS = 45; const len = RADIUS * 2 * Math.PI; const AnimatedCircle = Animated.createAnimatedComponent(Circle); class App extends Component { percent = new Animated.Value(0); startAnime = () => { Animated.timing(this.percent, { toValue: len, duration: 10*1000, useNativeDriver: true, easing: Easing.linear, }).start(); } render() { return ( <SafeAreaView style={styles.container}> <Svg height='50%' width='50%' viewBox='0 0 100 100'> <Circle cx='50' cy='50' r={`${RADIUS}`} stroke='blue' strokeWidth='1' strokeDasharray={[len, len]} strokeDashoffset={this.percent} /> <AnimatedCircle cx='50' cy='50' r={`${RADIUS}`} stroke='blue' strokeWidth='10' strokeDasharray={[len, len]} strokeDashoffset={this.percent} /> </Svg> <Button title='Start Anime' onPress={this.startAnime} /> </SafeAreaView > ); } } const styles = StyleSheet.create({ container: { justifyContent: 'center', alignItems: 'center', }, }); export default App;
補足
動作させるには、 https://github.com/react-native-community/react-native-svg が必要で、インストール方法は上記を参照。
Animated.Valueの一番簡単なサンプルは、React Nativeの標準ドキュメントにある。 https://reactnative.dev/docs/animated