@uiw/react-native
Version:
UIW for React Native
178 lines (171 loc) • 4.72 kB
JavaScript
import React, { useState, useEffect, useRef, useCallback } from 'react';
import { StyleSheet, View, Image, ScrollView, Dimensions, TouchableOpacity } from 'react-native';
import Loader from '../Loader';
import { colors } from '../utils';
const Swiper = porps => {
const gitwidth = Dimensions.get('window').width;
const {
dataSource = [],
width = gitwidth,
height = 130,
time = 6000,
autoplay = true,
borderRadius = 0,
dotStyle = 'dot',
loading = false,
index = 0
} = porps;
let [curIndex, setCurIndex] = useState(index);
let timer = useRef();
const scrollToRef = useRef();
// 设置初始变量
const onContentSizeChange = () => {
if (scrollToRef && scrollToRef.current && index !== 0) {
setCurIndex(index);
scrollToRef.current.scrollTo({
x: width * index,
y: 0,
animated: false
});
}
};
// 自动播放
const autoPlay = useCallback(() => {
clearInterval(timer.current);
timer.current = setInterval(() => {
let index = curIndex + 1;
if (curIndex === dataSource.length - 1) {
index = 0;
setCurIndex(0);
} else {
setCurIndex(curIndex + 1);
}
scrollToRef.current.scrollTo({
x: width * index,
y: 0,
animated: true
});
}, time);
}, [curIndex]);
// 开启播放
useEffect(() => {
if (autoplay && !loading) autoPlay();
}, [autoPlay]);
// 页面离开停止播放
useEffect(() => {
return () => {
clearInterval(timer.current);
};
}, []);
// 开始拖拽终止定时器
const onScrollBeginDrag = () => {
if (autoplay) {
clearInterval(timer.current);
// setCurIndex(0);
}
};
// 停止拖拽开启定时器
const onScrollEndDrag = () => {
if (autoplay) autoPlay();
};
const onMomentumScrollEnd = e => {
e.persist();
let offSetX = e.nativeEvent.contentOffset.x;
let mentWidth = e.nativeEvent.layoutMeasurement.width;
let page = offSetX / mentWidth;
if (page === dataSource.length) {
setCurIndex(0);
scrollToRef.current.scrollTo({
x: 0,
y: 0,
animated: false
});
} else {
setCurIndex(page);
}
};
// 点击原点跳转
const onClickDot = index => {
setCurIndex(index);
scrollToRef.current.scrollTo({
x: width * index,
y: 0,
animated: true
});
};
return <Loader loading={loading} rounded={5} maskColor="transparent">
<View style={StyleSheet.flatten([styles.banner, {
width,
height
}])}>
<ScrollView ref={scrollToRef} horizontal={true} showsHorizontalScrollIndicator={false} pagingEnabled={true} onScrollBeginDrag={onScrollBeginDrag} onScrollEndDrag={onScrollEndDrag} onMomentumScrollEnd={onMomentumScrollEnd} onContentSizeChange={onContentSizeChange}>
{[...dataSource, dataSource[0]].map((item, index) => {
return <View key={index} style={{
width,
height
}}>
<View style={{
padding: 12
}}>
<TouchableOpacity activeOpacity={1} onPress={() => {
item.onClick && item.onClick();
}}>
<Image key={index} style={StyleSheet.flatten([{
borderRadius,
width: '100%',
height: '100%'
}])} resizeMode="cover" source={typeof item.url === 'number' ? item.url : {
uri: item.url
}} />
</TouchableOpacity>
</View>
</View>;
})}
</ScrollView>
<View style={styles.dotBox}>
{dataSource.map((_, index) => {
return <TouchableOpacity onPress={onClickDot.bind(this, index)} key={index} style={StyleSheet.flatten([dotStyle === 'block' ? styles.block : styles.dot, index === curIndex ? styles.dotSetColor : styles.dotColor])} />;
})}
</View>
</View>
</Loader>;
};
const styles = StyleSheet.create({
banner: {
width: '100%',
position: 'relative',
overflow: 'hidden'
},
dotBox: {
width: '100%',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
bottom: 22
},
dot: {
width: 8,
height: 8,
borderRadius: 4,
marginTop: 0,
marginBottom: 0,
marginLeft: 8,
marginRight: 8
},
block: {
width: 16,
height: 3,
marginTop: 0,
marginBottom: 0,
marginLeft: 8,
marginRight: 8
},
dotColor: {
backgroundColor: colors.white
},
dotSetColor: {
backgroundColor: colors.colorsPalette.grey50
}
});
export default Swiper;