组件为js实现的圆形抽奖转盘
组件实现了请求响应前预旋转,待请求返回后决定旋转目标值。请求失败则复位提示。
具体实现
import React from 'react';
import {
View,
Image,
Text,
StyleSheet,
TouchableOpacity,
Animated,
Easing,
} from 'react-native';
import {unitWidth} from '../constants/Layout';
export default class TurnTable extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
rotatedDeg: new Animated.Value(0), // 旋转角度
};
this.luck = false; // 是否给按钮上锁
}
tryStart = () => {
if (this.luck) return;
this.props.tryStart && this.props.tryStart(); // 告诉父组件我要准备开始了
};
fakeStart = () => {// 数据响应前的旋转
this.luck = true;
Animated.timing(this.state.rotatedDeg, {
toValue: 60,
duration: 60000,
easing: Easing.linear,
}).start();
};
start = (type) => {// 数据响应后正式开始旋转
let tartV = this.state.rotatedDeg._value;
tartV = Math.ceil(tartV) + 3 - 0.08 * type;
Animated.timing(this.state.rotatedDeg, {
toValue: tartV,
duration: 3000,
easing: Easing.in,
}).start();
};
resetStatus = () => {//重置抽奖轮盘
this.state.rotatedDeg.setValue(0);
this.luck = false;
}
render(): React.ReactElement<any> | string | number | {} | React.ReactNodeArray | React.ReactPortal | boolean | null | undefined {
const {list} = this.props;
const {rotatedDeg} = this.state;
const RotateZ = rotatedDeg.interpolate({
inputRange: [0, 60],
outputRange: ['0deg', '43200deg'],
});
return (
<View
style={styles.box}
>
<Animated.View
style={[styles.move, {
transform: [
{rotateZ: RotateZ},
],
}]}
>
/** 轮盘背景 **/
<Image
source={require('../assets/images/components/turntable.png')}
style={[styles.move,]}
/>
/** 红包icon与配置文案 **/
{list.map((item, index) => (
<View key={index} style={[styles.priceBox, {
transform: [
{
rotate: index * 60 + 'deg'
}
]
}]}>
<Image
source={require('../assets/images/home/redpackage_logo.png')}
style={styles.priceBoxImg}
/>
<Text style={styles.priceTxt}>{item}元</Text>
</View>
))}
</Animated.View>
<TouchableOpacity
onPress={this.tryStart}
>
<Image
style={styles.btn}
source={require('../assets/images/components/turntablebtn.png')}
/>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
box: {
width: 684 * unitWidth,
height: 683 * unitWidth,
alignItems: 'center',
justifyContent: 'center',
},
move: {
width: 684 * unitWidth,
height: 683 * unitWidth,
position: 'absolute',
left: 0,
top: 0,
},
btn: {
width: 234 * unitWidth,
height: 242 * unitWidth,
},
priceBox: {
width: 93 * unitWidth,
height: 683 * unitWidth,
position: 'absolute',
left: 684 / 2 * unitWidth,
top: 0,
paddingTop: 80 * unitWidth,
marginLeft: -93 / 2 * unitWidth,
},
priceBoxImg: {
width: 93 * unitWidth,
height: 124 * unitWidth,
position: 'absolute',
left: 0,
top: 80 * unitWidth,
},
priceTxt: {
color: '#fff',
textAlign: 'center',
marginTop: 80 * unitWidth,
fontSize: 20 * unitWidth,
height: 28 * unitWidth,
lineHeight: 28 * unitWidth,
},
});