vue老虎机效果的简单实现

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            .slot {
                float: left;
                margin: 0.4em;
            }
            
            .slot__window {
                background-color: green;
                width: 200px;
                height: 200px;
                overflow: hidden;
            }
            
            .slot__wrap {}
            
            .slot__item {
                margin-top: 20px;
                height: 160px;
                width: 180px;
                padding: 0 10px;
                text-align: center;
                background-color: blue;
                color: white;
                line-height: 160px;
            }
            
            .slot__item--copy {}
        </style>
    </head>

    <body>
        <div id="app">
            <slot-machine ref="slot-machine"></slot-machine>
        </div>
    </body>
    <script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
</html>

<script type="text/javascript">
const next = window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    window.oRequestAnimationFrame || function(cb) { window.setTimeout(cb, 1000/60) }

const slotMachine = {
  data: function() {
      return {
      slots: [
        {title: "When",items: [
        "today","next week","last year","tomorrow","yesterday"
        ]},
        {title: "Where",items: [
        "at home","at work","at school","at the gym","at the park","at the beach","at the sidewalk","at the city",
        ]},
        {title: "How",items: [
        "cycling","walking","swimming","flying",
        ]}
      ],
      opts: null,
      startedAt: null,
    }
  },
  template: "<div class='slot-machine'> <button @click='start'>start</button> <div class='slot' v-for='slot in slots' ref='slots'> <h2>{{ slot.title }}</h2> <div class='slot__window'> <div class='slot__wrap'> <div class='slot__item' v-for='opt in slot.items'>{{ opt }}</div> <div class='slot__item slot__item--copy' >{{ slot.items[0] }}</div></div> </div> </div> </div>",
  methods: {
      start: function() {
      if (this.opts) {
        return
      }        
      this.opts = this.slots.map( (data, i) => {
        const slot = this.$refs.slots[i];// map(function(){})利用map便利slots的每一个选项组,最终得到return的返回值
        const choice = Math.floor( Math.random() * data.items.length );// 随机生成一个[0,data.items.length]的整数(floor向下取整)
        console.log("choice", i, data.items[choice])
        const opts = {
          el: slot.querySelector('.slot__wrap'),//指向奖项元素的父级;
          finalPos: choice * 180,// 180为每一个奖品滚动标签的高度;
//        startOffset: 2000 + Math.random() * 500 + i * 500,// 影响转的圈数
          startOffset:2000 + Math.random() * 500 + i * 500,// 影响转的圈数
          height: data.items.length * 180,
          duration: 3000 + i * 700, // milliseconds
          isFinished: false,
        }
        return opts
      })
//    console.log(this.opts);//这个时候this.opts已经和opts一模一样了
      next( this.animate );// 开启动画
      },
    animate: function(timestamp) {// timestamp当前的方法持续的毫秒数
      if (this.startedAt == null) {
          this.startedAt = timestamp// 动画初始时间
     }
      const timeDiff = timestamp - this.startedAt//动画持续的时间
      this.opts.forEach( opt => {
          if(opt.isFinished){
            return
        }
        const timeRemaining = Math.max(opt.duration - timeDiff, 0);// 总的持续时间 - 动画持续时间 = 剩下的时间,0表示结束
        const power = 3
        const offset = ( Math.pow(timeRemaining, power) / Math.pow(opt.duration, power) ) * opt.startOffset
        // Math.pow(timeRemaining, power)表示: timeRemaining 的3 次幂;
        // negative, such that slots move from top to bottom
        const pos = -1 * Math.floor((offset + opt.finalPos) % opt.height)
        opt.el.style.transform = "translateY(" + pos + "px)"
        
        if ( timeDiff > opt.duration ) {
//        console.log('finished', opt, pos, opt.finalPost)
            opt.isFinished = true
        }
        
      })  
      if (this.opts.every( o => o.isFinished )) {
          this.opts = null
        this.startedAt = null
//      console.log('finished')
      } else {
        next( this.animate )
      }
    } 
  }
}


new Vue({
  el : '#app',
  components: { slotMachine },
  data: function() {
      return {}
  }
})
</script>

猜你喜欢

转载自blog.csdn.net/szjSmiling/article/details/81780566
今日推荐