この記事はレコチョク Advent Calendar 2021の10日目の記事となります。
レコチョク・ラボの松木です。
仕事では主にレコチョク・ラボの取り組みをサポートしたり検証のためのプロトタイプを作ったりしています。
2021年も残り少しですが、おうち時間で楽器を楽しむ方が増えたというデータもあり、今年から新しく楽器をはじめた方もいるのではないでしょうか。
私は以前からサンプリングというものに興味があったので、サンプラーとマイクを使った遊びをはじめました。
作ったもの
今回作ったものはReact Nativeアプリケーションで動作する以下のようなアニメーションになります。
https://snack.expo.dev/@y-matsuki/wallet-like-ui
解説
今回実装するUIは react-native-snap-carousel をベースに実装しています。
コンポーネントの利用方法は以下です。
const { height } = Dimensions.get('window'); return ( <Carousel ref={carouselRef} data={items} renderItem={renderItem} vertical={true} enableSnap={false} layout={'default'} activeSlideAlignment={'start'} inactiveSlideScale={1} inactiveSlideOpacity={1} sliderHeight={height} itemHeight={54} scrollInterpolator={scrollInterpolator} slideInterpolatedStyle={animatedStyles} useScrollView={true} /> ); |
今回の実装で重要なポイントを以下に列挙します。
その他の属性についてはドキュメントを参照ください。
名称 | 説明 |
---|---|
data | リストのデータ |
renderItem | データを元にReactコンポーネントを返す関数(今回はカードを返す) |
itemHeight | 今回はカードの高さ300に対して54を指定することで重なりを表現する |
scrollInterpolator | スクロール位置に応じた挙動をカスタマイズする |
slideInterpolatedStyle | スクロール位置に応じたスタイルをカスタマイズする |
ドキュメントを参考にスクロールした際の挙動のカスタマイズします。「scrollInterpolator」についてはほぼそのまま利用したため「slideInterpolatedStyle」の話をします。
const animatedStyles = ( index: number, animatedValue: Animated.Value, carouselProps: CarouselProps<any> ): StyleProp<ViewStyle> => { const cardHeight = Math.floor((width / 16) * 9); return { zIndex: carouselProps.data.length - index, transform: [ { translateY: animatedValue.interpolate({ inputRange: [-1, 0, 1, 2], outputRange: [ -cardHeight * 0.2, // <- アクティブなカードの前のカード 0, // <- アクティブなカード(今回は一番上のカード) cardHeight * 1, // <- アクティブなカードの次のカード cardHeight * 1.2, // <- アクティブなカードの次の次のカード ], }), }, ], }; }; |
「animatedValue.interpolate()」関数を用いてスクロール時のスタイルの挙動アニメーションを定義します。「inputRange」がリスト内でのカードの位置を表しており「outputRange」がそれに対応するカードのスタイルを表します。
ちなみに「outputRange」を全て「0」にすると以下のようになります。(itemHeight = 54のため高さ54のリストとして描画される)
「transform.translateY」は「コンポーネントのY座標の位置を移動する」ことを表しており「cardHeight * 1.2」は「カードの高さの1.2倍の長さ(画面下部に)移動する」という意味になります。
アクティブなカードの前後を少しずつ上下に移動させてあげることで、アクティブなカードにアクセントを付けたUIを作ることができます。
また、zIndexの部分を以下のよう指定すると、カードの重なり順を逆にできます。
zIndex: carouselProps.data.length - index |
まとめ
iOSだとヌルヌル動くのですがAndroidの場合はshadowが効かなかったり動きが硬い感じでややイマイチでした。
今回の実装方法だとカードの枚数が多いとメモリを食うので、RecyclerView的な実装に改善するとより実用的と思います。
明日のレコチョク Advent Calendar 2021は11日目「家計簿のデータをNode.jsでスプレッドシート連携してみた」です。お楽しみに!
この記事を書いた人
最近書いた記事
- 2021.12.10React NativeでWallet風UIを実装する
- 2018.11.19Elasticsearchで簡単な検索とscoreを調整する方法
- 2018.10.05ECSをEC2からFargateに切り替える際の注意点
- 2018.09.12AKB48グループ映像倉庫のWeb版をリリースしました