#独家
Vue自拟弹幕组件bug寻求解答或提示?

2023-07-14 0 3,163

在尝试写一段弹幕组件,代码如下:

import { onMounted, ref, nextTick } from 'vue'
import io from 'socket.io-client'

export default {
  setup () {
    let socket
    const barrages = ref([]) // 存放弹幕数据
    const winWidth = ref(window.innerWidth) // 获得屏幕宽度
    const barrageEls = ref([]) // 获取每条弹幕

    onMounted(() => {
      socket = io('http://localhost:3002')
      socket.on('connect', () => {
        console.log(socket.id, '监听客户端连接成功-connect')
      })
      socket.on('to-client', async (data) => {

        // 计算最新一条弹幕的文字宽度,以便记录划出距离
        const canvas = document.createElement('canvas')
        const context = canvas.getContext('2d')
        context.font = '12pt Avenir'
        const {
          width
        } = context.measureText(data.name + data.discourse)

        // 追加弹幕到 barrages 中
        barrages.value[barrages.value.length] = {
          msg: data.name + ':' + data.discourse,
          speed: Math.round(Math.random() * 3), // 随机速度
          top: Math.round(Math.random() * 100)
        }

        await nextTick()

        // 弹幕画出动画
        const timer = setInterval(function () {
          // 获得新添加的弹幕 [barrageEls.value.length - 1] 并对其位置进行移动
          if (barrageEls.value[barrageEls.value.length - 1].offsetLeft < -(Math.ceil(width))) {
            // 停止动画本质是停止定时器
            clearInterval(timer)
          }
          barrageEls.value[barrageEls.value.length - 1].style.left = winWidth.value--
        }, Math.round(Math.random() * 3))
      })
    })

    return {
      barrages,
      barrageEls,
      winWidth
    }
  }
}

但实际运行起来发现有如下 bug :

  • 如果相近时间内提交两条弹幕,会导致速度叠加;
  • 每条弹幕的左坐标位置并没有随弹幕内容变化;
  • 在第一条弹幕移动时间内可以进行重复提交,但 clearInterval(timer) 后无法触发新弹幕滚动

目前还没有想到解决办法,还望可以得到提示,谢谢!


依照一楼的方案修改代码,解决了问题,但是又暴露了新的问题:
新的一条弹幕总会在视图上清楚上一条弹幕动画,我在想是否是因为 [barrageEls.value.length - 1] 的问题导致的,我尝试如下修改:

// 在新弹幕来的时候遍历对象判断该结束哪个动画
barrages.value.forEach(item => {
  if (item.left < -item.width) {
    clearInterval(item.timer)
  }
})
……
barrages.value.push({
  width: width, // 保存该弹幕宽度
  msg: data.name + ':' + data.discourse,
  speed: Math.round(Math.random() * 3),
  top: Math.round(Math.random() * 100),
  left: winWidth.value,
  timer: null // 保存该弹幕动画
})
……
const timer = setInterval(function () {
      // 将终止动画函数放到了外面
      barrages.value[barrages.value.length - 1].left--
      barrageEls.value[barrageEls.value.length - 1].style.left = barrages.value[barrages.value.length - 1].left + 'px'
}, Math.round(Math.random() * (10 - 5) + 5))
barrages.value[barrages.value.length - 1].timer = timer  // 存储定时器

但是依旧会清除前面的弹幕 ???


又修改了一版,解决了新弹幕清楚旧弹幕的问题,但是此写法无法终止定时器,代码如下:

<template v-for="(item, index) in barrages" :key="index">
  <div :style="{ top: item.top + '%', left: item.maxW + 'px' }">
    {{ item.timer(item) }} // 运行当前对象中的定时器函数
    {{ item.msg }}
  </div>
</template>

// 追加弹幕到 barrages 中
let newBarrage = {
  msg: data.name + ':' + data.discourse,
  top: Math.round(Math.random() * 100),
  speed: Math.round(Math.random() * (10 - 5) + 5),
  maxW: maxW, // maxW 屏幕总宽度
  minW: width, // width 当前弹幕占用宽度
  timer: (item) => {
    timer(item)
  }
}

function timer (item) {
  let timer = setInterval(() => {
    if (item.maxW < -item.minW) {
      clearInterval(timer) // 该方案此处无法终止定时器
    }
    item.maxW--
  }, item.speed)
}

barrages.value.push(newBarrage)

仍在想办法 Ing ……

import { onMounted, ref, nextTick } from 'vue'
import io from 'socket.io-client'

export default {
  setup () {
    let socket
    const barrages = ref([]) // 存放弹幕数据
    const winWidth = ref(window.innerWidth) // 获得屏幕宽度

    onMounted(() => {
      socket = io('http://localhost:3002')
      socket.on('connect', () => {
        console.log(socket.id, '监听客户端连接成功-connect')
      })
      socket.on('to-client', async (data) => {

        // 计算最新一条弹幕的文字宽度,以便记录划出距离
        const canvas = document.createElement('canvas')
        const context = canvas.getContext('2d')
        context.font = '12pt Avenir'
        const {
          width
        } = context.measureText(data.name + data.discourse)

        // 追加弹幕到 barrages 中
        const newBarrage = {
          msg: data.name + ':' + data.discourse,
          speed: Math.round(Math.random() * 3), // 随机速度
          top: Math.round(Math.random() * 100),
          left: winWidth.value,
          width: width,
          timer: null
        }
        barrages.value.push(newBarrage)

        await nextTick()

        // 弹幕画出动画
        newBarrage.timer = setInterval(function () {
          // 获得新添加的弹幕 [barrageEls.value.length - 1] 并对其位置进行移动
          if (newBarrage.left < -newBarrage.width) {
            // 停止动画本质是停止定时器
            clearInterval(newBarrage.timer)
          }
          newBarrage.left--
        }, newBarrage.speed)
      })
    })

    return {
      barrages,
      winWidth
    }
  }
}
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

1. JK下载官网所有资源来源于开发团队,加入会员即可下载使用!如有问题请联系右下角在线客服!
2. JK下载官方保障所有软件都通过人工亲测,为每位会员用户提供安全可靠的应用软件、游戏资源下载及程序开发服务。
3. JK开发团队针对会员诉求,历经多年拥有现今开发成果, 每款应用程序上线前都经过人工测试无误后提供安装使用,只为会员提供安全原创的应用。
4. PC/移动端应用下载后如遇安装使用问题请联系右下角在线客服或提交工单,一对一指导解决疑难。

JK软件下载官网 技术分享 Vue自拟弹幕组件bug寻求解答或提示? https://www.jkxiazai.com/2024.html

JK软件应用商店是经过官方安全认证,保障正版软件平台

相关资源

官方客服团队

为您解决烦忧 - 24小时在线 专业服务