vue2做的弹幕效果

2022-06-24  本文已影响0人  IamaStupid

vue2做的弹幕效果

image.png
<template>
  <div class="view-content home">
    <button @click="toggleDanmuAnimate">stop</button>
    <div class="danmu-box">
      <template v-for="(item, i) in danmuList">
        <div class="danmu-item" :key="'dm' + i" :style="{'left': item.left + 'px', top: item.top + 'px'}">{{item.text}}</div>
      </template>
    </div>
  </div>
</template>
<script>
let originData = []
let reqFrame = null
export default {
  name: "home-view",
  data: function () {
    return {
      btnToggle: false,
      winSize: null,
      addIndex: -1,
      danmuList: [],
      danmuBoxHeight: 0,
      danmuSpeed: 1,
      turnTime: 0,
      addOnceNum: 3
    };
  },
  created() {
    this.getWinInfo()
    this.danmuBoxHeight = 410 * this.winSize.rem / 100
    this.ajax()
  },
  methods:{
    getWinInfo() {
      let win = {
        w: window.innerWidth, h: window.innerHeight, rem: 0
      }
      let doc = document.documentElement.style.fontSize.replace('px', '') - 0
      if (doc > 0) {
        win.rem = doc
      }
      this.winSize = win
    },
    ajax() {
      setTimeout(() => {
        let data = [
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
          {text: '1111111111111111'},
          {text: 'tttttttt'},
        ]
        originData = data
        this.animateRequest()
      }, 2000)
    },
    isOutDanmu(item) {
      return item.left <= (this.winSize.w * -1)
    },
    animateRequest() {
      let tempArr = []
      let addNum = Math.floor(Math.random() * this.addOnceNum)
      if (this.addIndex === -1) {
        // 第一次 如果随机添加的数量是0,强制添加1个
        this.turnTime = 110
        if (addNum < 1) {
          addNum = 1
        }
      }
      // console.log('addNum:', addNum)
      if (addNum > 0 && this.turnTime > 100) {
        tempArr = originData.slice(this.addIndex + 1, this.addIndex + 1 + addNum)
        this.addIndex = this.addIndex + addNum
        this.turnTime = 0
      }
      tempArr = [].concat(this.danmuList, tempArr)
      tempArr.forEach((item, i) => {
        if(item.top === undefined || this.isOutDanmu(item)) {
          if (i === 0) {
            item.top = Math.floor(this.danmuBoxHeight / 2 - 50)
          } else {
            item.top = Math.floor(Math.random() * (this.danmuBoxHeight - 30))
            // 为防止弹幕重合
            if (Math.abs(item.top - tempArr[i - 1].top) < 25) {
              // 有可能重合了
              if (item.top > tempArr[i - 1].top) {
                // 两个60 25没有特殊联系,估摸着写的, 主要是为了不让弹幕的位置太靠下
                if (item.top > (this.danmuBoxHeight - 60)) {
                  item.top = item.top - 60
                } else {
                  item.top = item.top + 25
                }
              } else {
                item.top = item.top - 25
              }
            }
          }
          if (item.top < 0) {
            item.top = 0
          }
        }
        if(item.left === undefined || this.isOutDanmu(item)) {
          item.left = Math.floor(this.winSize.w * 1.1)
        } else {
          item.left -= this.danmuSpeed
          if (this.isOutDanmu(item)) {
            tempArr.splice(i, 1)
          }
        }
      })
      this.danmuList = tempArr
      this.turnTime++
      if (tempArr.length === 0) {
        this.addIndex = -1
      }
      reqFrame = window.requestAnimationFrame(this.animateRequest)
      // test code
      // if (this.addIndex < 50) {
      //   window.requestAnimationFrame(this.animateRequest)
      // }
    },
    toggleDanmuAnimate() {
      this.btnToggle = !this.btnToggle
      if (this.btnToggle) {
        window.cancelAnimationFrame(reqFrame);
        reqFrame = null
      } else {
        reqFrame = window.requestAnimationFrame(this.animateRequest)
      }
    }
  }
};
</script>
 <style lang="less" scoped>
 .danmu-box {
   width: 100%; height: 410px; position: absolute; left: 0; top: 266px; overflow: hidden; background: #f00;
   .danmu-item {
     display: inline-block; padding: 3px 8px; border-radius: 6px; background-color: rgba(0, 0, 0, 0.5);
     position: absolute; left: 110%; color: #fff;
   }
 }
</style>
上一篇 下一篇

猜你喜欢

热点阅读