


Reanimated を使用した React Native での自動スクロール、無限ループ、ページネーションを備えたカスタマイズ可能なカルーセルの構築
React Native でカスタム カルーセルを作成することは、アプリケーションに視覚的なセンスと対話性を追加する優れた方法です。このブログでは、React Native の Animated ライブラリと Reanimated ライブラリを使用して、自動スクロール機能を含むカルーセルを構築する方法を検討します。また、アニメーション化されたドットとエレガントな画像遷移効果を備えたページネーション システムも実装します。
概要
このチュートリアルでは、次の内容について説明します:
- カスタム カルーセル コンポーネントをセットアップします。
- スムーズなアニメーションと補間のために Reanimated を使用します。
- 画像間を自動的に回転する自動スクロール機能。
- アニメーション化されたドットインジケーターを使用した ページネーション システムを構築します。
構築するもの:
- アニメーショントランジションを備えた水平スクロールカルーセル。
- ユーザーがカルーセルを操作すると一時停止する自動スクロール。
- 現在表示されているアイテムに基づいて更新されるページ分割ドット。
始めましょう!
1. カルーセルコンポーネントのセットアップ
まず、カルーセルのコア ロジックを収容する CustomCarousel コンポーネントを作成します。主な要素は次のとおりです:
- アイテムをレンダリングするための Animated.FlatList。
- setInterval を使用した自動スクロールメカニズム。
- Reanimated のスクロールToとトランジションをアニメーション化するための useSharedValue。
/* eslint-disable react-native/no-inline-styles */ import React, { useEffect, useRef, useState } from 'react'; import { StyleSheet, View, useWindowDimensions } from 'react-native'; import Animated, { scrollTo, useAnimatedRef, useAnimatedScrollHandler, useDerivedValue, useSharedValue, } from 'react-native-reanimated'; import { hpx } from '../../helpers'; import Pagination from './Pagination'; import RenderItem from './RenderItem'; import { animals } from './constants'; const CustomCarousel = () => { const x = useSharedValue(0); const [data, setData] = useState(animals); const { width } = useWindowDimensions(); const [currentIndex, setCurrentIndex] = useState(0); const [paginationIndex, setPaginationIndex] = useState(0); const ref = useAnimatedRef(); const [isAutoPlay, setIsAutoPlay] = useState(true); const interval = useRef(); const offset = useSharedValue(0); console.log('CURRENT_CAROUSEL_ITEM?', paginationIndex); const onViewableItemsChanged = ({ viewableItems }) => { if (viewableItems[0].index !== undefined && viewableItems[0].index !== null) { setCurrentIndex(viewableItems[0].index); setPaginationIndex(viewableItems[0].index % animals.length); } }; const viewabilityConfig = { itemVisiblePercentThreshold: 50, }; const viewabilityConfigCallbackPairs = useRef([{ viewabilityConfig, onViewableItemsChanged }]); const onScroll = useAnimatedScrollHandler({ onScroll: (e) => { x.value = e.contentOffset.x; }, onMomentumEnd: (e) => { offset.value = e.contentOffset.x; }, }); useDerivedValue(() => { scrollTo(ref, offset.value, 0, true); }); useEffect(() => { if (isAutoPlay === true) { interval.current = setInterval(() => { offset.value += width; }, 4000); } else { clearInterval(interval.current); } return () => { clearInterval(interval.current); }; }, [isAutoPlay, offset, width]); return ( <View style={styles.container}> <Animated.FlatList ref={ref} style={{ height: hpx(194), flexGrow: 0 }} onScrollBeginDrag={() => { setIsAutoPlay(false); }} onScrollEndDrag={() => { setIsAutoPlay(true); }} onScroll={onScroll} scrollEventThrottle={16} horizontal bounces={false} pagingEnabled showsHorizontalScrollIndicator={false} viewabilityConfigCallbackPairs={viewabilityConfigCallbackPairs.current} onEndReached={() => setData([...data, ...animals])} onEndReachedThreshold={0.5} data={data} keyExtractor={(_, index) => `list_item${index}`} renderItem={({ item, index }) => { return <RenderItem item={item} index={index} x={x} />; }} /> <Pagination paginationIndex={paginationIndex} /> </View> ); }; export default CustomCarousel; const styles = StyleSheet.create({ container: { flex: 1, }, buttonContainer: { justifyContent: 'center', alignItems: 'center', flexDirection: 'row', gap: 14, }, });
2. ページネーションコンポーネント
ページネーション コンポーネントには、現在アクティブなスライドを示すドットが表示されます。各ドットの不透明度は、カルーセルの現在のインデックスに応じて変化します。
import React from 'react'; import { StyleSheet, View } from 'react-native'; import { hpx } from '../../helpers'; import Dot from './Dot'; import { animals } from './constants'; const Pagination = ({ paginationIndex }) => { return ( <View style={styles.container}> {animals.map((_, index) => { return <Dot index={index} key={index} paginationIndex={paginationIndex} />; })} </View> ); }; export default Pagination; const styles = StyleSheet.create({ container: { flexDirection: 'row', marginTop: hpx(16), justifyContent: 'center', alignItems: 'center', }, });
3. ドットコンポーネント
Dot コンポーネントは、ページネーション システム内の個々のドットの外観を処理します。ドットがアクティブ (現在のインデックス) であるかどうかに基づいてスタイルを変更します。
import React from 'react'; import { StyleSheet, View } from 'react-native'; import { Colors } from '../../assets'; import { hpx, wpx } from '../../helpers'; const Dot = ({ index, paginationIndex }) => { return <View style={paginationIndex === index ? styles.dot : styles.dotOpacity} />; }; export default Dot; const styles = StyleSheet.create({ dot: { backgroundColor: Colors.white, height: hpx(3), width: wpx(12), marginHorizontal: 2, borderRadius: 8, }, dotOpacity: { backgroundColor: Colors.white, height: hpx(3), width: wpx(12), marginHorizontal: 2, borderRadius: 8, opacity: 0.5, }, });
4. RenderItem コンポーネント
RenderItem コンポーネントは各カルーセル項目を表示します。 Reanimated の補間機能を利用して、スクロールに応じてアイテムの不透明度をアニメーション化します。
import React from 'react'; import { StyleSheet, useWindowDimensions, View } from 'react-native'; import Animated, { Extrapolation, interpolate, useAnimatedStyle } from 'react-native-reanimated'; import { hpx, nf, SCREEN_WIDTH, wpx } from '../../helpers/Scale'; const RenderItem = ({ item, index, x }) => { const { width } = useWindowDimensions(); const animatedStyle = useAnimatedStyle(() => { const opacityAnim = interpolate( x.value, [(index - 1) * width, index * width, (index + 1) * width], [-0.3, 1, -0.3], Extrapolation.CLAMP ); return { opacity: opacityAnim, }; }); return ( <View style={{ width }}> <Animated.Image resizeMode="cover" source={{ uri: item.image }} style={[styles.titleImage, animatedStyle]} /> </View> ); }; export default RenderItem; const styles = StyleSheet.create({ titleImage: { width: SCREEN_WIDTH - wpx(32), // adjust the width of the image and horizontal padding height: hpx(194), alignSelf: 'center', borderRadius: nf(16), }, });
5. 自動スクロール
自動スクロール機能は、setInterval を使用して実装されます。この方法では、カルーセルが 4 秒ごとに 1 つのスライドから次のスライドに自動的に移動します。ユーザーがドラッグしてカルーセルを操作すると、自動スクロールが一時停止します。
6. 定数ファイル
/* eslint-disable react-native/no-inline-styles */ import React, { useEffect, useRef, useState } from 'react'; import { StyleSheet, View, useWindowDimensions } from 'react-native'; import Animated, { scrollTo, useAnimatedRef, useAnimatedScrollHandler, useDerivedValue, useSharedValue, } from 'react-native-reanimated'; import { hpx } from '../../helpers'; import Pagination from './Pagination'; import RenderItem from './RenderItem'; import { animals } from './constants'; const CustomCarousel = () => { const x = useSharedValue(0); const [data, setData] = useState(animals); const { width } = useWindowDimensions(); const [currentIndex, setCurrentIndex] = useState(0); const [paginationIndex, setPaginationIndex] = useState(0); const ref = useAnimatedRef(); const [isAutoPlay, setIsAutoPlay] = useState(true); const interval = useRef(); const offset = useSharedValue(0); console.log('CURRENT_CAROUSEL_ITEM?', paginationIndex); const onViewableItemsChanged = ({ viewableItems }) => { if (viewableItems[0].index !== undefined && viewableItems[0].index !== null) { setCurrentIndex(viewableItems[0].index); setPaginationIndex(viewableItems[0].index % animals.length); } }; const viewabilityConfig = { itemVisiblePercentThreshold: 50, }; const viewabilityConfigCallbackPairs = useRef([{ viewabilityConfig, onViewableItemsChanged }]); const onScroll = useAnimatedScrollHandler({ onScroll: (e) => { x.value = e.contentOffset.x; }, onMomentumEnd: (e) => { offset.value = e.contentOffset.x; }, }); useDerivedValue(() => { scrollTo(ref, offset.value, 0, true); }); useEffect(() => { if (isAutoPlay === true) { interval.current = setInterval(() => { offset.value += width; }, 4000); } else { clearInterval(interval.current); } return () => { clearInterval(interval.current); }; }, [isAutoPlay, offset, width]); return ( <View style={styles.container}> <Animated.FlatList ref={ref} style={{ height: hpx(194), flexGrow: 0 }} onScrollBeginDrag={() => { setIsAutoPlay(false); }} onScrollEndDrag={() => { setIsAutoPlay(true); }} onScroll={onScroll} scrollEventThrottle={16} horizontal bounces={false} pagingEnabled showsHorizontalScrollIndicator={false} viewabilityConfigCallbackPairs={viewabilityConfigCallbackPairs.current} onEndReached={() => setData([...data, ...animals])} onEndReachedThreshold={0.5} data={data} keyExtractor={(_, index) => `list_item${index}`} renderItem={({ item, index }) => { return <RenderItem item={item} index={index} x={x} />; }} /> <Pagination paginationIndex={paginationIndex} /> </View> ); }; export default CustomCarousel; const styles = StyleSheet.create({ container: { flex: 1, }, buttonContainer: { justifyContent: 'center', alignItems: 'center', flexDirection: 'row', gap: 14, }, });
7. 結論
このチュートリアルでは、React Native の FlatList と、スムーズなアニメーションと補間のための Reanimated を使用してカスタム カルーセルを構築しました。アニメーション化されたドットと自動スクロール機能を備えたページネーション システムを追加し、ユーザー インタラクションによって自動スクロール機能が一時停止および再開されるようにしました。
これらのコンポーネントを使用すると、カルーセルを拡張して、動的コンテンツ、クリック可能な項目、より洗練されたアニメーションなどの他の機能を組み込むことができます。 Reanimated による React Native の柔軟性により、最小限のパフォーマンス コストで高度にカスタマイズ可能なカルーセルが可能になり、視覚的に魅力的なモバイル アプリの作成に最適です。
プロジェクトでこれを自由に試して、デザインのニーズに合わせてスタイルと動作をカスタマイズしてください。
以上がReanimated を使用した React Native での自動スクロール、無限ループ、ページネーションを備えたカスタマイズ可能なカルーセルの構築の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











フロントエンドのサーマルペーパーチケット印刷のためのよくある質問とソリューションフロントエンド開発におけるチケット印刷は、一般的な要件です。しかし、多くの開発者が実装しています...

JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

スキルや業界のニーズに応じて、PythonおよびJavaScript開発者には絶対的な給与はありません。 1. Pythonは、データサイエンスと機械学習でさらに支払われる場合があります。 2。JavaScriptは、フロントエンドとフルスタックの開発に大きな需要があり、その給与もかなりです。 3。影響要因には、経験、地理的位置、会社の規模、特定のスキルが含まれます。

この記事の視差スクロールと要素のアニメーション効果の実現に関する議論では、Shiseidoの公式ウェブサイト(https://www.shisido.co.co.jp/sb/wonderland/)と同様の達成方法について説明します。

JavaScriptを学ぶことは難しくありませんが、挑戦的です。 1)変数、データ型、関数などの基本概念を理解します。2)非同期プログラミングをマスターし、イベントループを通じて実装します。 3)DOM操作を使用し、非同期リクエストを処理することを約束します。 4)一般的な間違いを避け、デバッグテクニックを使用します。 5)パフォーマンスを最適化し、ベストプラクティスに従ってください。

JavaScriptの最新トレンドには、TypeScriptの台頭、最新のフレームワークとライブラリの人気、WebAssemblyの適用が含まれます。将来の見通しは、より強力なタイプシステム、サーバー側のJavaScriptの開発、人工知能と機械学習の拡大、およびIoTおよびEDGEコンピューティングの可能性をカバーしています。

同じIDを持つ配列要素をJavaScriptの1つのオブジェクトにマージする方法は?データを処理するとき、私たちはしばしば同じIDを持つ必要性に遭遇します...

Zustand非同期操作のデータの更新問題。 Zustand State Management Libraryを使用する場合、非同期操作を不当にするデータ更新の問題に遭遇することがよくあります。 �...
