碎碎念
一直很忙很少有空写点东西,难得闲下来,还是记录下作为怀念。关于React看过文档,很多东西还在摸索中。没想到来到掘金的第一篇文章既然是关于React的,觉得不错的点个赞,哪里需要改进还望各路大大指点!。
附录
-
- DEMO中使用styled-component,请自行了解.
-
- 欢迎扩展使用.
一、读前思考,如下图换做你需要考虑哪些地方?
实际中至少要注意到以下几点:
-
1、用户是否有资格参与?(抽奖剩余次数,是否绑定手机号,实名认证等...)
-
2、点击开始启动转盘,同时要做到几点:
- 1):禁止用户再次再次点击开始按钮
- 2):剩余次数要减少一次
- 3):动画要由快到慢的缓慢去执行
-
3、何时停下?(由接口控制如:礼物id),既然由接口控制又会出现:
- 1):接口正确返回礼物id在客户端礼物列表中存在,正常逻辑
- 2):接口正确返回但是礼物id在客户端列表中不存在
- 2):接口超时
- 3):接口返回错误
-
4、如果没有抽奖限制(只要有次数就能抽奖),至于是先从接口拿要停下的结果还是一边启动转盘同时去拿结果,根据实际应用中适当处理
-
5、转盘停止需要一个弹框告诉用户中了什么
-
6、转盘未停止再次点击需要给用户提示信息
-
7、如果没资格(没次数,没认证...)也需要给用户提示信息
二、简单分析:这里只展示部分代码
- 1、初始化组件状态和部分参数,React中是当前组件的状态(state)变化就会触发render重新渲染组件
constructor(props) {
super(props)
this.state = {
giftList: getGift(),
// 一圈的总长度,礼物总数量
stepCount: getGift().length,
// 剩余抽奖次数,接口返回
myCount: 5,
// 转动激活位置默认:1,动态,可设置(>=1&&<=stepCount)
activeIndex: 1,//这里从1开始对应数组的下标0
// 最终要停下的位置:接口返回(>=1&&<=stepCount)
endStopIndex: 14,
// 抽奖是否正在进行中
isDrawing: false,
// 转速 分别为最后0,1,2,3,4,5圈的转速
speed: [336, 168, 84, 42, 42, 42],
// 抽獎結果的禮物名字
showDialog: false,
gotGift: null,
// 消息提示框
message: null,
messageType: null,
animationName: null,
};
// 开启转盘的定时器
this.timer = null;
//alert message list
this.messageInfo = {
success: {
message: "恭喜您中奖了!",
//提示消息的进场动画
animationName: null
},
warning: {
message: "抽奖进行中,请稍后再试!",
animationName: "slideInLeft"
},
error: {
message: "抽奖次数不足,抓紧去完成任务获得抽奖资格吧~",
animationName: "shake",
},
}
}
复制代码
2、点击开始获得停下的位置,需要重置的当前状态。实际中要:从接口获取礼物id,根据id获得对应礼物和要停下的位置(1-18)。其实点击开始的时候就知道获得哪个礼物了~
let {endStopIndex} = 17;
let myCount = this.state.myCount - 1;
// 开启转盘,当前抽奖状态设置为true正在抽奖中,并准备启动动画:startRun
this.setState({isDrawing: true, endStopIndex, myCount}, this.startRun);
复制代码
3、准备转动,调用只移动一步的方法
startRun() {
// 总共需要转的圈数
let leftRound = this.state.speed.length - 1;
this.addOneStep({isContinue: true, leftRound})
}
复制代码
4、移动一步的同时需要重置选中状态,那如何再移动一步?定时器递归调用该移动一步的方法,注意参数变化(特别是如何让动画由快缓慢的变慢),当最后一圈的时候在停在要停的位置。最主要的一部分!
/*
* 每次增加一步,满一圈,总圈数-1同时速度变慢,直到最后一圈停在指定位置
* 直到知道结果,慢慢变慢速度,停在结果那;
* 转盘停到结果值时,重置初始值({isDrawing:false});
*
* Function addOneStep
* 奖品位置移动一步
* @isContinue {Booleans} 是否应该继续这个定时器
* @leftRound {Number} 剩余几圈 3代表一个无限大的值,因为还不知道结果
*/
addOneStep = (params) => {
let {activeIndex, stepCount, speed} = this.state;
let {isContinue, leftRound} = params;
activeIndex += 1;
if (isContinue) {
// 如果到超过奖品个数,重置为1
if (activeIndex > stepCount) {
console.log(`转了${leftRound}圈`);
// 圈数减少的同时转动的速度要变慢!!!!!!
leftRound -= 1;
activeIndex = 1;
}
// 如果已经到最后一圈了 且 已经到了指定要中奖的位置了 就不需要继续了
if (leftRound === 0 && activeIndex === this.state.endStopIndex) {
console.log(`現在停在:${this.state.endStopIndex}`);
isContinue = false;
}
this.setState({activeIndex});
const nextParams = {
isContinue,
leftRound,
};
this.timer = setTimeout(() => {
this.addOneStep(nextParams)
}, speed[leftRound]);//下一次移动的一步的速度
} else {
clearTimeout(this.timer);
this.timer = null;
let gotGift = this.state.giftList[this.state.endStopIndex - 1];
this.setState({
isDrawing: false,
gotGift,
showDialog: true,
});
this.alertMessage("success")
}
}
复制代码
5、停下之后抽奖结束,弹框获得提示信息告诉用户中了什么!
三、提示
- 1、有些地方根据实际应用中变化,如礼物个数,开始的位置,转动速度,转动圈数等
- 2、鄙人最开始写的时候动画由快变慢非常明显,经高人指点,得出这个有快变慢的缓动效果
- 3、DEMO中用了某直播平台的礼物图片如有不适请告知。