React Nativeのアニメーションことはじめ

react-native-reanimated(reanimated2)とreact-native-gesture-handlerを用いたアニメーションについて、概念の理解などに苦しんだので備忘録。
素人ですので、間違えなどあればご指摘いただけると幸いです。


## 一番簡単なアニメーション(PanGesture)
```typescript
import * as React from "react";
import { StyleSheet, View } from "react-native";
import Animated, {
  useAnimatedGestureHandler,
  useAnimatedStyle,
  useSharedValue,
  withSpring,
} from "react-native-reanimated";
import {
  PanGestureHandler,
  PanGestureHandlerGestureEvent,
} from "react-native-gesture-handler";


interface ContextInterface {
  translateX: number;
  translateY: number;
};

export default function PanGestureScreen() {
  const translateX = useSharedValue(0);
  const translateY = useSharedValue(0);

  const panGestureEvent = useAnimatedGestureHandler<
    PanGestureHandlerGestureEvent,
    ContextInterface
  >({
    onStart: (event, context) => {
      // contextはgesture中に自在にアクセスできるobject 自分が必要な値をstart時にもたせて置くことで、他のeventの際にその値を参照できる
      context.translateX = translateX.value;
      context.translateY = translateY.value;
    },
    onActive: (event, context) => {
　　　// gesutreスタート時の位置とtransltaion分の位置を足して現在の位置を算出する
      translateX.value = event.translationX + context.translateX;
      translateY.value = event.translationY + context.translateY;
    },
    onEnd: (event) => {}
  });

  const reanimatedStyle = useAnimatedStyle(() => {
    return {
      transform: [
        {
          translateX: translateX.value,
        },
        {
          translateY: translateY.value,
        },
      ],
    };
  });

  return (
    <View style={styles.container}>
      <PanGestureHandler onGestureEvent={panGestureEvent}>
        // 以下の四角いViewがアニメーションする
        <Animated.View style={[styles.square, reanimatedStyle]} />
      </PanGestureHandler>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
  },
  circle: {
    width: 200,
    height: 200,
    alignItems: "center",
    justifyContent: "center",
    borderRadius: 100,
    borderWidth: 5,
    borderColor: "rgba(0,0,256,0.5)",
  },
});


```

### 動作例
![pangesture.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630070/8595133e-18ed-139a-ef9b-f41179bca79a.gif)

#react native で gesture & animationを実装するために必要な概念
## ①JS thread と UI thread
react nativeでは大きく分けて上記の２つのthreadを考えることができる
UI thireadは60frames(コマ送り)/1秒 で動いており、JS threadとは非同期でやり取りしている。
このやり取りの中で、UI threadからanimationに関するframeの要求がJS threadに送られ、それをresponse するという動作が16.6(=1/60)ミリ秒以内に完結しないと、frame dropがおきてアニメーションがぎこちなくなってしまう(UXが低下してしまう)。 
このような問題の対策としてreact-native-reanimatedとreact-native-gesture-handlerから提供されるapiがある。これらのapiは
**全てのgestureとanimataionに関するメソッドなどをUI側で宣言して、２つのthreadでのやり取りをなくす** 
つまり、animationのeventが生じるだけではUI threadとJS threadは疎通しないのでスムーズにアニメーションできる
  

## ②よく出てくる用語やapiの考え方
<dl>
<dt> useSharedValue</dt>  
<dd>UI thread と JS thread でshareできる値を提供するapi  
js thread(react native)から由来するアニメーションを可能にする
</dd>

<dt> worklet</dt>  
<dd>関数にこのディレクティブを指定すると その関数がコンパイルされてUI thireadに送られ、UI thiread側で実行できるようになる</dd>


<dt>interpolate (和訳: 補間)</dt>
<dd>shared valueをアニメーションしやすい値に補間するためのapi  
e.g. shared valueが0から1にアニメーションし、interpolateによって0から360に補間してrotateの角度をアニメーションさせる  
他にも rgba表記のcolorな
どもアニメーションせさられる。</dd>
</dl>

***
#### 参考
公式(reanimated2):  https://docs.swmansion.com/react-native-reanimated/
公式(gesture-handler):  https://docs.swmansion.com/react-native-gesture-handler/
worklet :  https://www.youtube.com/watch?v=6dDpggVnZPo
william's tutorial at freeCodeCamp.org   :  https://www.youtube.com/watch?v=wEVjaXK4sYQ
https://chrizog.com/react-native-rotation-anchor-point