在尝试写一段弹幕组件,代码如下:
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
最终使用组件解决,传送门链接: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 } }}
Mudu.Room.Barrage 弹幕组件 Barrage.New事件 Barrage.New事件会在收到新的弹幕时被触发 Mudu.MsgBus.On( // 事件名,值为"Barrage.New" "Barrage.New", // 事件处理函数,参数为弹幕对象 function (barrage) { barrage = JSON.parse(barrage)
本文向大家介绍详解用vue编写弹出框组件,包括了详解用vue编写弹出框组件的使用技巧和注意事项,需要的朋友参考一下 前言 最近研究了用vue编写弹出框的组件,发现其实这里面的门道还是有很多的。这篇文完全是用来记录总结下最近的学习成果,同时也希望能够帮得上正在学习纠结的你~ps:本文假设你已经了解vue2.0相关框架,因此适合有一定vue2.0基础的同学阅读。 设计组件的思考 其实单纯的编写一个弹出
在view/HomeView.vue使用自定义组件时一直找不到,只能在App.vue里能找到, 报错:No loader is configured for ".vue" files: packages/components/card/Card.vue
本文向大家介绍Vue.js路由组件vue-router使用方法详解,包括了Vue.js路由组件vue-router使用方法详解的使用技巧和注意事项,需要的朋友参考一下 使用Vue.js + vue-router 创建单页应用是非常简单的。只需要配置组件和路由映射,然后告诉 vue-router 在哪里渲染即可。 一、普通方式基本例子: 二、块化机制编程基本例子,以在vue-cli中的使用方法为例
对于vue响应式原理,里面的watcher。有个疑问。 (1)每个组件只有一个watcher,当数据被读取会被添加到相应的dep中。 (2)在某处用到该数据就会new一个新的watcher,然后添加到dep中呢。 这两种说法哪个对? 给出两个例子,帮忙分析,感谢。 例如,这个图片中dep1和dep2。如果按说法(1),那图中的三个watcher应该是同一个。但是vue官方文档的说法是图2到底哪个才
本文向大家介绍很棒的vue弹窗组件,包括了很棒的vue弹窗组件的使用技巧和注意事项,需要的朋友参考一下 弹窗是一个项目必备的复用利器,所以封装起来,保证项目ui一致,是很有必要的。学了一段时间vue,想想还是用vue写一下吧。用的很小白,但是会写出来了,说明我也有进步一丢丢了。继续加油…. 代码贴图如下,样式比较丑,不要介意… 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐