function RaffleRotate(option) { this.prizeNums = option.prizeNums; // 奖项个数 this.prizeDeg = 360 / option.prizeNums; // 每个奖项所占的角度 this.activePrize = 0; // 抽中的奖项序号 0角度的奖项对应最后一个序号: 比如6个奖项,0角度时的奖项序号是6 this.rotateDom = null; if(option.rotateDom) { this.rotateDom = option.rotateDom; } this.endCallback = option.endCallback || function() {}; // 转动结束时的回调函数 this.preTimestamp = 0; //前一次requestAnimationFrame调用的时刻 this.originalStartTimes = 0; // 转动动画最开始的时间点 this.easeOutSatrtDeg = 0; // 开始减速时rotateDom转动的角度 this.easeOutTimer = 0; // 减速转动开始的时刻 this.easeOutEndDeg = 0; // 减速转动结束时rotateDom应该停留的角度 this.deg = 0; // rotateDom的实时角度 this.maxSpeed = 20; // 转动的最大速度 this.isRotating = false; // 是否正在旋转中 this.forceStop = false; } RaffleRotate.prototype = { constructor: RaffleRotate, raffleRotaing: function() { var self = this; function rotating(timestamp) { if(self.forceStop) { self.forceStop = false; return; } if (self.preTimestamp === undefined) { self.preTimestamp = timestamp; // 初始化 } var totalElapsed = timestamp - self.originalStartTimes; // 从动画开始到此刻的时间间隔 var fps = timestamp - self.preTimestamp; // 两次requestAnimationFrame调用的时间间隔 屏幕刷新帧率 // 从0速度开始加速直到maxSpeed self.deg = self.deg + self.easeIn(totalElapsed,0,self.maxSpeed,2000); self.deg = self.deg % 360; // 防止角度值过大 // console.log(deg); if(self.rotateDom) { self.rotateDom.style.transform = 'rotate(' + self.deg + 'deg)'; } self.preTimestamp = timestamp; if(self.activePrize > 0) { self.easeOutTimer = timestamp;// Date.now(); // 开始减速时rotateDom转动的角度 self.easeOutSatrtDeg = self.deg; let i = 0; while(++i) { // 结合开始减速时所处的位置和结束时所处的位置计算旋转总路程 const endDeg = 360 * i - (self.activePrize * self.prizeDeg) - self.easeOutSatrtDeg; // 计算刚开始第一帧旋转的角度,也就是初始速度 const curSpeed = self.easeOut(fps, self.easeOutSatrtDeg, endDeg, 2000) - self.easeOutSatrtDeg; // 当初始速度与当前旋转最大速度相等,即可获取总共需要旋转的角度 if (curSpeed >= self.maxSpeed) { self.easeOutEndDeg = endDeg; break; } } // 开始减速 return self.slowDown(); } window.requestAnimationFrame(rotating); } window.requestAnimationFrame(function(timestamp) { self.originalStartTimes = timestamp; rotating(timestamp); }); }, slowDown: function () { var self = this; window.requestAnimationFrame(function(timestamp) { // 开始减速时刻到此时刻的时间间隔 const timeInterval = timestamp - self.easeOutTimer; // 减速完成 if (timeInterval >= 2000) { self.isRotating = false; self.endCallback({ index: self.activePrize, deg: self.deg }); self.resetInit(); return; } // 缓出减速 self.deg = self.easeOut(timeInterval, self.easeOutSatrtDeg, self.easeOutEndDeg, 2000) % 360; if(self.rotateDom) { self.rotateDom.style.transform = 'rotate('+ self.deg+ 'deg)'; } self.slowDown(); }); }, forceStopRotating: function() { this.forceStop = true; }, setActivePrizeIndex: function(index) { this.activePrize = index; }, resetInit: function() { this.forceStop = false; this.activePrize = 0; }, // t:缓动开始时间 ms // b:缓动开始位置 deg // c:缓动移动的距离 deg // d:缓动持续的时间 ms // 结果值为当前位置值 deg // 缓入函数 easeIn: function (t, b, c, d) { if (t >= d) t = d; // 除法赋值(/=)运算符将变量除以右操作数的值,并将结果赋值给该变量。 return c * (t /= d) * t + b; }, // 缓出函数 easeOut: function (t, b, c, d) { if (t >= d) t = d; return -c * (t /= d) * (t - 2) + b; } }; export { RaffleRotate }