[react Nativeアニメーション]波の作成🌊


最近svgアニメーションを利用してグラフを描いたことがありますが、おもしろいですね.だから私たちはアニメーションの実施シリーズを始めます!
RN开発者たちアニメ顽张れ!
--
--
では、最初のアニメは私の好きな波です.🌊から.

使用するライブラリ

  • react-native-svg
  • react-naitve-reanimated
  • ライブラリの設定については、各ホームページを参照してください:)

    Svg


    まず、波を収容するためにSVGを設定します.
    import React from 'react';
    import Svg from 'react-native-svg';
    
    const SIZE = 300;
    
    export default function Wave() {
      return (
        <Svg style={{width: SIZE, height: SIZE}} viewBox="0 0 1 1" />
      );
    }

    簡単にsvgを紹介します。


    n/a.方向


    svgはx,y軸に沿って移動するが,y軸は逆方向である.
    したがって,y軸の値が大きいほど下になる.私も最初は戸惑いました.🤨

    viewBox


    ViewBoxの最初の2つの数字はsvgの起点を表しています.
    次の2つの位置は、SVGでstyleとして指定されたwidthとheightがどのような割合で表示されるかを定義する値です.
    SVGの幅と高さが300 pxに設定されている場合、viewBox="0 0 1 1".
    基準点は(0, 0),横300 pxは1,縦300 pxは1であった.
    これで最大長さを1と考えることができるので、比率を計算するときは直感的でいいです!
    ǖ約画素値を使用したい場合は、下記のようにSIZE値を入れてください.
    return (
        <Svg style={{width: SIZE, height: SIZE}} viewBox={`0 0 ${SIZE} ${SIZE}`} />
      );

    波を描く


    svgで最も自由度の高いパスを使って、波が打つ前の様子を描きましょう.
    曲線を描くときは制御点しか覚えていません!
    svgでは曲線を描く方法が多いですが、今回はBézier曲線のCubic曲線を使います.

    前述したようにカーブを描くには、
    2個の
  • 制御点
  • 終了点座標

  • 全部で3つの座標が必要です.
    (開始点は前の値です.)

    上の図では、一番左側の点が始点で、残りの3つの点のうち、曲線に存在しない2つの点が制御点です.
    制御点の位置によって弧の形が異なることを覚えておいてください.
    これを波の形にして
    import React from 'react';
    import Svg, {Path} from 'react-native-svg';
    
    const SIZE = 300;
    
    export default function Wave() {
      const d = [
        'M 0 0.5',
        'C 0.3 0.2, 0.7 0.8, 1 0.5'
      ].join(" ");
      
      return (
        <Svg style={{width: SIZE, height: SIZE}} viewBox="0 0 1 1">
          <Path d={d} fill="#1F5E9D" />
        </Svg>
      );
    }
    パスの各コードを開きます.
  • pathの起点は(0,0.5),最左正中間である.
  • 制御点の最初の(c 1)は(0.3,0.2)、左上角である.
  • 第2(c 2)は(0.7,0.8)、右下角である.
  • 曲線の終点は(1,0.5)、右端の真ん中です.

  • 2つの制御点はそれぞれ上部と下部に位置するため、正弦波図形で表すことができる.
    カーブは完了しましたが...波に見えないでしょ?
    私たちは下を埋めるべきだと思います.🤔
    export default function Wave() {
      const d = [
        'M 0 0.5',
        'C 0.3 0.2, 0.7 0.8, 1 0.5',
        'V 1',
        'H 0'
      ].join(" ");
      
      return (
        <Svg style={{width: SIZE, height: SIZE}} viewBox="0 0 1 1">
          <Path d={d} fill="#1F5E9D" />
        </Svg>
      );
    }
    Vは垂直方向のコマンドであり、Hは水平方向から対応する座標までの直線である.
    波が終わる右ボートの中央点(1,0.5)
    1まで下へ(H 1)
    そして左に0(V 0)まで漕ぎます!

    今こそ越える波のようだ!

    行動を起こす


    RNでアニメーションを実装する方法では、RNが提供するデフォルトのAnimated APIを使用する必要があったが、これは根本的な性能の問題である.
    魔法のように性能の問題を解決できるリネームライブラリが登場してから、RNアニメーションの希望だと思います.🧙

    どこを変えるべきですか?


    波に打たれたいなら、どこがどうなるのか.
    しばらく考える時間-!
    ...
    ...
    ...
    さっそくすぐ~
    制御点の位置はy軸方向に往復移動すればよい.
    制御点の変化によって曲線が変化し、制御点の位置が変化しないようにします.
    繰り返し、
    変えたら波が揺れるでしょう?

    useSharedValue


    今はエンコード時間です
    reanimatedライブラリは、reactでuseState hook定義値を使用するようにuseSharedValue hookを使用します.
    波の曲線が上下に移動するため、変更する値は制御点のy値です.
    export default function Wave() {
      const c1y = useSharedValue(0.2);
      const c2y = useSharedValue(0.8);
      
      const d = [
        'M 0 0.5',
        `C 0.3 ${c1y.value}, 0.7 ${c2y.value}, 1 0.5`,
        'V 1',
        'H 0'
      ].join(" ");
      
      return (
        <Svg style={{width: SIZE, height: SIZE}} viewBox="0 0 1 1">
          <Path d={d} fill="#1F5E9D" />
        </Svg>
      );
    }
    c1yおよびc2yを使用して宣言し、値の使用時にuseSharedValueキーを使用してアクセスおよび保存された値を使用します.

    動き出す。


    移動するには、useSharedValueとして保存した値を変更する必要があります.
    値を変更する方法は簡単です.
    割り当てるだけです.
    c1y.value = 0.8;
    c2y.value = 0.2;
    最初の制御点(c 1)は下に下がります.
    2番目の制御点(c 2)を上にします.
    2つの制御点の方向を完全に逆にしようとします.
    ボタンを作成し、そのボタンを押すと移動させます.
    export default function Wave() {
      const c1y = useSharedValue(0.2);
      const c2y = useSharedValue(0.8);
    
      const d = [
        'M 0 0.5',
        `C 0.3 ${c1y.value}, 0.7 ${c2y.value}, 1 0.5`,
        'V 1',
        'H 0',
      ].join(' ');
    
      const handleWave = () => {
        c1y.value = 0.8;
        c2y.value = 0.2;
      };
    
      return (
        <>
          <Button title="파도야 처라!" onPress={handleWave} />
          <Svg style={{width: SIZE, height: SIZE}} viewBox="0 0 1 1">
            <Path d={d} fill="#1F5E9D" />
          </Svg>
        </>
      );
    }
    

    ボタンを押すと!
    .
    .
    .
    動かない.😬

    どうして動かないのですか。


    値段も変えたのに、どうして動かないのですか.
    長文に注意...🚨
    RNは主に以下の内容から構成される.
  • JS Thread
  • UI Thread
  • Bridge
  • RNが基本的に提供するAnimated APIには根本的な話題があると言っていましたアニメーション計算はJS Threadで行われ、Bridgeを介してUI Threadに値が渡され、画面に表示されます.

    したがって、JS Threadでアニメーション値を計算しながら他の値を計算すると、アニメーションを処理する際にいくつかの困難が発生します.

    この問題を解決したのは、名前を変更したライブラリです.アニメーション計算もUI Threadによって処理されるため、計算値がBridgeを経ずに画面に直接表示されるため、再調整されたアニメーションはよりスムーズになります.

    だから何の関係があるの?


    sharedValueはUI ThreadとJS Threadで変更できますが、UI Threadでは同期して更新され、JS Threadでは非同期で更新されます.
    つまり、JS Threadで更新を行うと、すぐには変化せず、次のレンダリング後に変化します.setStateに似ています.
      const handleWave = () => {
        c1y.value = 0.8;
        c2y.value = 0.2;
      };
    JS ThreadではhandleWave関数が使用されているため、非同期で更新され、画面に表示されません.

    同期更新


    では、sharedValueが変更されたときにレンダリングする必要があります.
    実際には、Reanimatedで作成したhookを使用して、実装を簡素化できます.

    useAnimatedProps


    変更する値はパスパス(d)の値であるため、ユーザアニメーションコンフィギュレーションで定義されたpropsを使用して同期更新できます.
    userAnimatedPropsとして定義された値を使用するには、通常のSVGパスではなく、animatedPropsとして定義された構成部品を使用します.(再起動したAnimatedを使用する必要があります.)
    import Animated, {
    	useAnimatedProps,
    } from 'react-native-reanimated';
    
    const AnimatedPath = Animated.createAnimatedComponent(Path);
    
    export default function Wave() {
      const c1y = useSharedValue(0.2);
      const c2y = useSharedValue(0.8);
    
      const animatedProps = useAnimatedProps(() => {
        return {
          d: [
            'M 0 0.5',
            `C 0.3 ${c1y.value}, 0.7 ${c2y.value}, 1 0.5`,
            'V 1',
            'H 0',
          ].join(' '),
        };
      });
    
      const handleWave = () => {
        c1y.value = 0.8;
        c2y.value = 0.2;
      };
    
      return (
        <>
          <Button title="파도야 처라!" onPress={handleWave} />
          <Svg style={{width: SIZE, height: SIZE}} viewBox="0 0 1 1">
            <AnimatedPath animatedProps={animatedProps} fill="#1F5E9D" />
          </Svg>
        </>
      );
    }
    今ボタンをもう一度押し直しましょうか?

    やっと変えた!
    でも感情がないと急に変わってしまうのが残念
    変化の過程を見せたい

    withTiming


    時間とともに変化するすべてのプロシージャを表示します.
    詳細については、ドキュメントを参照してください.
    const handleWave = () => {
      c1y.value = withTiming(0.8, {duration: 500});
      c2y.value = withTiming(0.2, {duration: 500});
    };

    もうすぐ着きます.
    波が動き続けるように、この作業を繰り返すといいでしょう.

    withRepeat

      const handleWave = () => {
        c1y.value = withRepeat(withTiming(0.8, {duration: 500}), -1, true);
        c2y.value = withRepeat(withTiming(0.2, {duration: 500}), -1, true);
      };
    withRepeatの最初のパラメータは繰り返しアニメーションで、
    2つ目は繰り返し回数(-1は無限)
    3つ目のケースは、繰り返し終了するたびに逆方向になります.

    元気になったようでちょっと...気まずいです.
    制御点が同時に動いているので、波が片側に向かって動いている感じがなく、その場でうごめく.
    では、制御点の異なる移動タイミングをあげましょうか?

    withDelay

      const handleWave = () => {
        c1y.value = 
          withRepeat(withTiming(0.8, {duration: 500}), -1, true));
        c2y.value = withDelay(
          200,
          withRepeat(withTiming(0.2, {duration: 500}), -1, true),
        );
      };
    アニメーションをc 2で200ミリ秒遅れて起動させます.
    では結果を見てみましょう!?!?

    私はとても喜んでいます。🌊 🏄‍♂️


    タカの群れ


    このように書くと、面白そうですが、ずいぶん曲がりくねっています.ほほほ
    仕上げに4時間以上かかりましたでも久しぶりにやりたい開発をしたので、時間がどうやって過ぎたのか分からずに打ち込むことができました.
    これからもアニメシリーズをアップしていきます!私のために!ははは
    コードを襟に置いた!
    https://github.com/dipsiiiiiiiiii/reanimated-playgrounds/blob/master/src/screens/wave/Wave.js
    それでは皆さん今日も頑張ります.👍