转盘类型抽奖如何实现

需求

常规转动,如ease-in-out

这种方案适合已经得知中奖信息,得到旋转角度,直接旋转就ok

:style="{transform:rotate(360deg),transition:rotate_transition}"

transform:旋转的角度

transition:过渡方式。如:'transform 3s ease-in-out'

mark transition需要事件触发,所以没法在网页加载时自动发生。所以,只要让transfor或transition变动一次,动画就会执行一次

🙋🏻♀️:点击开始,给style赋值就ok了。transform每次赋值只有不一样,才会动。这就是transition的含义:过渡

rotate_deg = 'rotate(360deg)'

rotate_transition = 'transform 3s ease-in-out'

随机控制开始-旋转-结束

上面的方案适合内定中奖名单,不用考虑接口请求,😈。但如果要是随机中奖呢:开始抽奖,去向接口要中奖信息,接口返回中奖奖品,再决定转盘旋转多少。这种旋转时间是不一定的。啥时候结束旋转取决于接口什么时候返回。

效果:启动 - 加速 - 匀速 - 减速 - 停止

mark 动画效果取决于transform:结束到开始的差值,duration内执行完。。结束值大于初始值,就是正转。反之是反转

封装js控制工具

  • rotate.js
/**
 * mark: 入参interval都是秒,这里具体用到的地方*1000了
 * @param el 入参需要旋转的标签元素
 * @param stepDeg 标签元素step时间需要旋转的角度 360度是一圈
 */
export function doInifityRotate(el) {
  // 每一次的旋转,记录旋转的deg,下次更新style需要在totaldeg累加,规则:如果是大于totaldeg,正转。如果小于totaldeg,反转
  var hasDeg = 0
  // 每一次的旋转,记录已经旋转的时间
  var hasDura = 0

  var easeInImpl = (function() {
    return function($el, duration, deg) {
      hasDeg += deg
      hasDura += duration
      $el.style = 'transform:rotate(' + hasDeg + 'deg);' + 'transition:transform ' + duration + 's ease-in'
    }
  })()

  var interval
  var linearForeverImpl = (function() {
    return function($el, stepInterval, stepDeg) {
      interval = setInterval(() => {
        hasDeg += stepDeg
        hasDura += stepInterval
        $el.style = 'transform:rotate(' + hasDeg + 'deg);' + 'transition:transform ' + stepInterval + 's linear'
      }, (stepInterval * 1000))
      console.log('=====interval ' + interval)
    }
  })()

  var linearImpl = (function() {
    return function($el, duration, deg) {
      hasDeg += deg
      hasDura += duration
      $el.style = 'transform:rotate(' + hasDeg + 'deg);' + 'transition:transform ' + duration + 's linear'
    }
  })()

  var easeOutImpl = (function() {
    return function($el, duration, deg, targetDeg, callBack) {
      if (interval) {
        clearInterval(interval)
      }
      // 1、指定的多转的角度
      hasDeg += deg
      hasDura += duration
      // 2、向上取整到360度的倍数
      const lackDeg = 360 - (hasDeg % 360)
      hasDeg += lackDeg
      // 3、角度落到具体扇区
      hasDeg -= targetDeg
      $el.style = 'transform:rotate(' + hasDeg + 'deg);' + 'transition:transform ' + duration + 's ease-out'
      setTimeout(() => {
        callBack()
      }, (duration * 1000 + 50))
    }
  })()

  var stopImpl = (function() {
    return function($el) {
      console.log(hasDura)
      if (interval) {
        clearInterval(interval)
      }
      hasDura = 0
      hasDeg = 0
      $el.style = ''
    }
  })()

  return {
    easeIn: function(duration, deg) {
      // resetImpl(el)
      console.log('=== ease in')
      easeInImpl(el, duration, deg)
    },
    linearForever: function(stepInterval, stepDeg) {
      linearForeverImpl(el, stepInterval, stepDeg)
    },
    linear: function(duration, deg) {
      linearImpl(el, duration, deg)
    },
    /**
     *
     * @param duration 动画时长
     * @param deg 动画角度
     * @param targetDeg 0度起到奖品落到的角度。比如 需要把指针落到第二个扇区,那就需要多转45度
     */
    easeOut: function(duration, deg, targetDeg, callBack) {
      easeOutImpl(el, duration, deg, targetDeg, callBack)
    },
    stop: function() {
      stopImpl(el)
    }
  }
}

  • 使用
// 开始请求网络 获取本次抽奖中奖信息
      this.prize()

// 转盘控制组件
      var rotate = doInifityRotate(this.$refs['wheel'])
      
// 开始旋转:加速旋转
      rotate.easeIn(2, 720)
// 加速2s后,开始匀速旋转
      setTimeout(() => {
        rotate.linearForever(0.01, 6)
      }, 2000)

// 此间,持续关注着网络请求结果。这里控制了阈值4s
      var interval
      var time = 0
      interval = setInterval(() => {
        time++
        if (Object.keys(this.raffledPrize).length > 0) {
          // 抽到奖了
          clearInterval(interval)
          const that = this
          // 具体的奖品在奖盘上的位置角度
          const targetDeg = this.getTargetDeg()
          
          if (time > 4000) {
          // 减速旋转,直到结束,停到奖品对应的角度位置
            rotate.easeOut(2.5, 720, targetDeg, function() {
            // 中奖后的操作
              that.wheelOver()
            })
          } else {
          // 这里表示,如果网络请求很快,从开始旋转到中奖结果回来,不够4s,那就转够4s。然后开始减速-结束
            setTimeout(() => {
              rotate.easeOut(2.5, 720, targetDeg, function() {
                that.wheelOver()
              })
            }, (4000 - time))
          }
        } else if (this.raffleError) {
          // 抽奖请求失败
          clearInterval(interval)
          const that = this
          setTimeout(() => {
            rotate.stop()
            that.isAllowClick = true
          }, 2100)
        }
      }, 1000)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容

  • 今天的任务是做一个纯CSS3的还算比较漂亮的抽奖大转盘,也就是下图效果。 我只说思路和重要的CSS3代码。 外盘 ...
    microkof阅读 4,997评论 7 5
  • html + css原生实现的,放在哪里都可以用,中奖奖品是可控的。还是直接上代码吧```<!DOCTYPE ht...
    木_子李阅读 2,848评论 0 2
  • Mobile Web Favorites 参与贡献 移动前端开发收藏夹,欢迎使用Issues以及 Pull Req...
    柴东啊阅读 723评论 0 2
  • <!DOCTYPE html> Document *{margin: 0;padding: 0;}p{te...
    极爷的皇纲阅读 410评论 0 0
  • 看了很多视频、文章,最后却通通忘记了,别人的知识依旧是别人的,自己却什么都没获得。此系列文章旨在加深自己的印象,因...
    DCbryant阅读 1,854评论 0 4