🛤️

【Flutter】5分でParallax Animationを実装する👅【Flutter Hooks】

2021/10/11に公開

どうも、はがくんです。

今回は、Flutter( + Flutter Hooks) でParallax Animationを実装していきます。
https://twitter.com/hagakun_yakuzai/status/1447192308491833346?s=20

Parallax Animationとは💡

Parallaxを直訳すると「視差」のことです。
あぁ、数学や物理の時間がやって来たと思いましたが、簡単にイメージできる例があります。

電車の窓です。

電車の窓を覗くと、山など遠くにあるものは遅く動いて見えます。
逆に、近くにある草や家はものすごく速く動いて見えますよね。

このように、同軸の動きに差をつけることで、立体感を感じさせるアニメーションのことをParallax Animationと呼ぶようです。(間違ってたらごめんなさい🙏)

Parallax Animationの実装準備⚙️

https://pub.dev/packages/flutter_hooks
今回はFlutter Hooksを使って実装していきます。
適当な画像を3枚用意しておきましょう。

PageControllerと現在位置を入れるフックの用意

PageView.builderを使って実装していくので、Controllerと、現在位置を入れるフックを用意しておきます。

    final pageState = usePageController();
    final selectedIndex = useState<double>(0);

pageState.pageから現在のスクロール位置を取り出せるので、それをselectedIndexに入れてあげます。

    final pageState = usePageController();
    final selectedIndex = useState<double>(0);
    
+    useEffect(() {
+      pageState.addListener(() {
+        selectedIndex.value = pageState.page!;
+        print(selectedIndex.value);
+      });
+    }, []);

PageView.builderに画像を配置して、Alignment Widgetを使ってParallax Animationを実装する

PageView.builder(
          scrollDirection: Axis.horizontal,
          itemCount: 999,
          controller: pageState,
          itemBuilder: (context, index) => Container(
            padding: const EdgeInsets.only(right: 20),
            child: Container(
              padding: const EdgeInsets.all(20),
              child: ClipRRect(
                borderRadius: BorderRadius.circular(16),
                child: Image.asset(
                  'assets/public${index % 3}.jpg',
                  alignment:
+                      Alignment(-selectedIndex.value * 4 + (index * 4), 0),
                  height: 370,
                  fit: BoxFit.cover,
                ),
              ),
            ),
          ),
        );

重要なのはもちろんここです。
Alignment(-selectedIndex.value * 4 + (index * 4), 0)
1つ目の引数はx軸、2つ目の引数はy軸座標を表しています。
https://api.flutter.dev/flutter/painting/Alignment-class.html

これによって、Containerの動きとImageのx軸の動きに差がつくため、ParallaxなAnimationがつくというわけ。

ここで、*4している理由は、動きの差を大きくしたいからです。
適当な数値なんでもOKです。今回は少し派手に動かしたかったので4にしていますが、あまり派手に動かすと酔うので低めの数値に設定したほうが良いかもしれません。

割と簡単に実装できた

どうでしたか?
理論など考え出すと難しく感じるかもしれませんが、実際のところ30行足らずのコードでParallax Aniamtionを実装できました。

Stateful Widgetを使った実装はコチラ。
https://www.youtube.com/watch?v=8Rl47Eb0rjg

Discussion