Vue自拟弹幕组件bug寻求解答或提示?
在尝试写一段弹幕组件,代码如下:
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 ……
最终使用组件解决,传送门链接:https://www.skypack.dev/view/vue3-danmaku
回答:
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
}
}
}
回答:
最终使用组件解决,传送门链接:https://www.skypack.dev/view/vue3-danmaku
以上是 Vue自拟弹幕组件bug寻求解答或提示? 的全部内容, 来源链接: utcz.com/p/934607.html