116 lines
2.9 KiB
TypeScript
116 lines
2.9 KiB
TypeScript
import React, { useRef, useState, useCallback } from "react";
|
|
import {
|
|
View,
|
|
Image,
|
|
FlatList,
|
|
TouchableOpacity,
|
|
Dimensions,
|
|
StyleSheet,
|
|
} from "react-native";
|
|
import Carousel from "react-native-reanimated-carousel";
|
|
|
|
const { width } = Dimensions.get("window");
|
|
const THUMB_SIZE = 64;
|
|
const SPACING = 10;
|
|
|
|
const images = [
|
|
require("../../../assets/images/big-product-detail.png"),
|
|
require("../../../assets/images/big-product-detail.jpg"),
|
|
require("../../../assets/images/big-product-detail-2.jpg"),
|
|
require("../../../assets/images/big-product-detail-3.jpg"),
|
|
require("../../../assets/images/big-product-detail-4.jpg"),
|
|
];
|
|
|
|
const ImageGallery = () => {
|
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
const carouselRef = useRef<Carousel<any>>(null);
|
|
const thumbnailListRef = useRef<FlatList>(null);
|
|
|
|
const scrollToThumbnail = useCallback((index: number) => {
|
|
const offset = index * (THUMB_SIZE + SPACING) - width / 2 + THUMB_SIZE / 2;
|
|
thumbnailListRef.current?.scrollToOffset({
|
|
offset: Math.max(0, offset),
|
|
animated: true,
|
|
});
|
|
}, []);
|
|
|
|
const onSnapToItem = useCallback(
|
|
(index: number) => {
|
|
setActiveIndex(index);
|
|
scrollToThumbnail(index);
|
|
},
|
|
[scrollToThumbnail]
|
|
);
|
|
|
|
const onThumbnailPress = useCallback((index: number) => {
|
|
carouselRef.current?.scrollTo({ index, animated: true });
|
|
}, []);
|
|
|
|
const renderThumbnail = useCallback(
|
|
({ item, index }: { item: any; index: number }) => (
|
|
<TouchableOpacity onPress={() => onThumbnailPress(index)}>
|
|
<Image
|
|
source={item}
|
|
style={[
|
|
styles.thumbnail,
|
|
activeIndex === index && styles.activeThumbnail,
|
|
]}
|
|
/>
|
|
</TouchableOpacity>
|
|
),
|
|
[activeIndex, onThumbnailPress]
|
|
);
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
<Carousel
|
|
ref={carouselRef}
|
|
loop={false}
|
|
width={width}
|
|
height={300}
|
|
data={images}
|
|
scrollAnimationDuration={400}
|
|
renderItem={({ item }) => (
|
|
<Image source={item} style={styles.bigImage} resizeMode="contain" />
|
|
)}
|
|
onSnapToItem={onSnapToItem}
|
|
/>
|
|
|
|
<FlatList
|
|
ref={thumbnailListRef}
|
|
data={images}
|
|
horizontal
|
|
keyExtractor={(_, i) => i.toString()}
|
|
renderItem={renderThumbnail}
|
|
showsHorizontalScrollIndicator={false}
|
|
contentContainerStyle={styles.thumbList}
|
|
/>
|
|
</View>
|
|
);
|
|
};
|
|
|
|
export default ImageGallery;
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {},
|
|
bigImage: {
|
|
width: width - 40,
|
|
height: 280,
|
|
borderWidth: 1,
|
|
borderColor: "#b1b1b1",
|
|
borderRadius: 12,
|
|
},
|
|
thumbnail: {
|
|
width: THUMB_SIZE,
|
|
height: THUMB_SIZE,
|
|
marginRight: SPACING,
|
|
borderRadius: 6,
|
|
borderWidth: 1,
|
|
borderColor: "#b1b1b1",
|
|
},
|
|
activeThumbnail: {
|
|
borderColor: "#1877F2",
|
|
},
|
|
thumbList: {},
|
|
});
|