1. 程式人生 > >React九宮格抽獎

React九宮格抽獎

body 點擊 truct his bsp 操作 clas 抽獎 section

思路:

一、.九宮格,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超時,轉盤會一直轉,返回異常則清除定時器。


  

React九宮格抽獎