• React九宫格抽奖


    思路:

    一、.九宫格,8个奖项,中心1个抽奖按钮。

    二、转的方向是顺时针,也就是说转的顺序如图:0-1-2-3-4-5-6-7。

    0 1 2
    7 3
    6 5 4

    三、如何排版?
        1.如果flex排版:

           优点:样式布局简单点;

      缺点:数据和旋转的顺序不一致,可以处理数据改变数据的排序,后续获得奖项,转到对应的位置,又需要处理一次数据。


           2.绝对定位:

      优点:把数据通过定位的方式,让数据和旋转顺序一致,数据操作简单。
         缺点:9个宫格需要一个个定位,稍微麻烦一点。

      刚开始选择的flex布局,后来后端交互的时候,只返回中奖奖品名称。需要做过多的数据处理。最终选择了绝对定位。

    四、设计一个定时器,接受3个参数: position-起始序号, result-结果序号, speed-速度。

      1.当用户点击抽奖,设置0位置开始,设置一个大于30s的result,设置一个speed速度,开启定时器,请求抽奖接口,返回结果后,清除定时器,并获取此时转盘停止的奖项序号。

      2.再次设置一个慢一点的速度,开启定时器,传入起始位置,算出停止位置距离0位置的补差个数,result=补差个数+中奖结果的序号,设置一个慢一点speed速度,再把他转完。

    代码

    一、请求后端接口,获取8个项品,处理数据,然后css去定位九宫格

    // 定义timer定时器,按钮状态可点击
    constructor(props) {
      super(props);
      this.timer;
      this.state = {
        dataSource: [],
        isDisabled: false,
        prizeName: ''
      }
    }
    // componentWillReceiveProps生命周期中处理
    if(data){
      data.map((v,i)=>{
        Object.assign(v,{ isActive: false, index: 's1', classText: 'p1' });
      })    
      data[0].isActive = true;
      this.setState({ data });
    }
    
    
    // render中 return()
    <div className="draw-section">
      {dataSource &&
        dataSource.map((v, i) => (
          <div
            key={v.id}
            className={v.isActive ? `draw-item active p${i}` : `draw-item p${i}`}
          >
            <img src={v.imgUrl} alt="" />
            <p className='item-prize-name'>{v.prizeName}</p>
          </div>
        ))
      }
      <div className="draw-item draw-btn">
        <input type="button" className="btn" onClick={this.handleClick} disabled={this.state.isDisabled} />
        <p className='draw-times'>抽奖次数*{this.state.total}</p>
      </div>
    </div>

    二、点击抽奖,执行handleClick方法。

     this.start(0, 999999, 50);  //  开启定时器,转盘转动
     this.draw();           // 发起一个请求,获取奖品  
    start = (position, result, speed) => {
      // position-起始序号  result-结果序号  speed-速度
      this.round = 0;   // 总次数
      this.active = position; // 起始位置
      const { dataSource } = this.state;
      // console.log('dataSource', dataSource);
      this.timer = setInterval(() => {
        if (this.round < result) {
          if (this.active === 7) {
            this.active = 0;
          } else {
            this.active += 1;
          }
          this.round += 1;
          for (let i = 0, l = dataSource.length; i < l; i += 1) {
            if (i === this.active) {
              dataSource[i].isActive = true;
            } else {
              dataSource[i].isActive = false;
            }
          }
          this.setState({ dataSource, activeIndex: this.active });
          // console.log('timer', this.active);
        } else {
          setTimeout(() => {
            this.setState({ prizeModal: true, isDisabled: false });
          }, 1000);
          clearInterval(this.timer);
        }
      }, speed);
    }

    三、接口返回结果后,在componentWillReceiveProps生命周期中,延时2s清除第一个定时器,接着开启新的定时器转到中奖位置。

    setTimeout(() => {
      const { activeIndex } = this.state;
      // 清除定时器
      clearInterval(this.timer);
      // 获取清除上一次定时器时停在的activeIndex为开启下一个定时器起始位置,并补上未转一整圈的个数,
      this.start(activeIndex, (8 - activeIndex) + resultIndex, 400);
    }, 2000);

    四、其他需要考虑的,如果接口30s超时,转盘会一直转,返回异常则清除定时器。


      

  • 相关阅读:
    ecplise自动提示失效,使用补全自动提示快捷键(Alt+/),但只显示“No Default Proposals”
    maven构建ssh工程
    pom.xml中坐标的组成
    依赖传递的规则
    maven中导入包版本冲突的解决
    maven工程的拆分与聚合
    maven的生命周期
    maven的常用命令
    在pom.xml中引入jar包坐标的依赖范围
    【stl的神奇操作】用集合搞定区间相交
  • 原文地址:https://www.cnblogs.com/hcxwd/p/9371165.html
Copyright © 2020-2023  润新知