rafflerotating.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. function RaffleRotate(option) {
  2. this.prizeNums = option.prizeNums; // 奖项个数
  3. this.prizeDeg = 360 / option.prizeNums; // 每个奖项所占的角度
  4. this.activePrize = 0; // 抽中的奖项序号 0角度的奖项对应最后一个序号: 比如6个奖项,0角度时的奖项序号是6
  5. this.rotateDom = null;
  6. if(option.rotateDom) {
  7. this.rotateDom = option.rotateDom;
  8. }
  9. this.endCallback = option.endCallback || function() {}; // 转动结束时的回调函数
  10. this.preTimestamp = 0; //前一次requestAnimationFrame调用的时刻
  11. this.originalStartTimes = 0; // 转动动画最开始的时间点
  12. this.easeOutSatrtDeg = 0; // 开始减速时rotateDom转动的角度
  13. this.easeOutTimer = 0; // 减速转动开始的时刻
  14. this.easeOutEndDeg = 0; // 减速转动结束时rotateDom应该停留的角度
  15. this.deg = 0; // rotateDom的实时角度
  16. this.maxSpeed = 20; // 转动的最大速度
  17. this.isRotating = false; // 是否正在旋转中
  18. this.forceStop = false;
  19. }
  20. RaffleRotate.prototype = {
  21. constructor: RaffleRotate,
  22. raffleRotaing: function() {
  23. var self = this;
  24. function rotating(timestamp) {
  25. if(self.forceStop) {
  26. self.forceStop = false;
  27. return;
  28. }
  29. if (self.preTimestamp === undefined) {
  30. self.preTimestamp = timestamp; // 初始化
  31. }
  32. var totalElapsed = timestamp - self.originalStartTimes; // 从动画开始到此刻的时间间隔
  33. var fps = timestamp - self.preTimestamp; // 两次requestAnimationFrame调用的时间间隔 屏幕刷新帧率
  34. // 从0速度开始加速直到maxSpeed
  35. self.deg = self.deg + self.easeIn(totalElapsed,0,self.maxSpeed,2000);
  36. self.deg = self.deg % 360; // 防止角度值过大
  37. // console.log(deg);
  38. if(self.rotateDom) {
  39. self.rotateDom.style.transform = 'rotate(' + self.deg + 'deg)';
  40. }
  41. self.preTimestamp = timestamp;
  42. if(self.activePrize > 0) {
  43. self.easeOutTimer = timestamp;// Date.now();
  44. // 开始减速时rotateDom转动的角度
  45. self.easeOutSatrtDeg = self.deg;
  46. let i = 0;
  47. while(++i) {
  48. // 结合开始减速时所处的位置和结束时所处的位置计算旋转总路程
  49. const endDeg = 360 * i - (self.activePrize * self.prizeDeg) - self.easeOutSatrtDeg;
  50. // 计算刚开始第一帧旋转的角度,也就是初始速度
  51. const curSpeed = self.easeOut(fps, self.easeOutSatrtDeg, endDeg, 2000) - self.easeOutSatrtDeg;
  52. // 当初始速度与当前旋转最大速度相等,即可获取总共需要旋转的角度
  53. if (curSpeed >= self.maxSpeed) {
  54. self.easeOutEndDeg = endDeg;
  55. break;
  56. }
  57. }
  58. // 开始减速
  59. return self.slowDown();
  60. }
  61. window.requestAnimationFrame(rotating);
  62. }
  63. window.requestAnimationFrame(function(timestamp) {
  64. self.originalStartTimes = timestamp;
  65. rotating(timestamp);
  66. });
  67. },
  68. slowDown: function () {
  69. var self = this;
  70. window.requestAnimationFrame(function(timestamp) {
  71. // 开始减速时刻到此时刻的时间间隔
  72. const timeInterval = timestamp - self.easeOutTimer;
  73. // 减速完成
  74. if (timeInterval >= 2000) {
  75. self.isRotating = false;
  76. self.endCallback({
  77. index: self.activePrize,
  78. deg: self.deg
  79. });
  80. self.resetInit();
  81. return;
  82. }
  83. // 缓出减速
  84. self.deg = self.easeOut(timeInterval, self.easeOutSatrtDeg, self.easeOutEndDeg, 2000) % 360;
  85. if(self.rotateDom) {
  86. self.rotateDom.style.transform = 'rotate('+ self.deg+ 'deg)';
  87. }
  88. self.slowDown();
  89. });
  90. },
  91. forceStopRotating: function() {
  92. this.forceStop = true;
  93. },
  94. setActivePrizeIndex: function(index) {
  95. this.activePrize = index;
  96. },
  97. resetInit: function() {
  98. this.forceStop = false;
  99. this.activePrize = 0;
  100. },
  101. // t:缓动开始时间 ms
  102. // b:缓动开始位置 deg
  103. // c:缓动移动的距离 deg
  104. // d:缓动持续的时间 ms
  105. // 结果值为当前位置值 deg
  106. // 缓入函数
  107. easeIn: function (t, b, c, d) {
  108. if (t >= d) t = d;
  109. // 除法赋值(/=)运算符将变量除以右操作数的值,并将结果赋值给该变量。
  110. return c * (t /= d) * t + b;
  111. },
  112. // 缓出函数
  113. easeOut: function (t, b, c, d) {
  114. if (t >= d) t = d;
  115. return -c * (t /= d) * (t - 2) + b;
  116. }
  117. };
  118. export { RaffleRotate }