React-Native抽奖

组件为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,
  },
});

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。