美文网首页
vue 直播弹幕功能

vue 直播弹幕功能

作者: 小蝴蝶_037a | 来源:发表于2020-03-13 14:56 被阅读0次

需求是不重叠弹幕
公司使用的是云信接发消息,我的思路是给直播间四条弹幕跑道,接收到弹幕之后往跑道内插入弹幕
以下是其中一条弹幕跑道的html:

        <div class="trumpet-box box1" v-for="(item,index) in list[0]">
                <div class="trumpet-item">
                    <div class="top">
                        <i v-show="item.barrageType === 64"></i>
                        <span v-show="item.grade>5"></span>
                        <p>{{item.userNickname}}</p>
                    </div>
                    <div class="bottom">
                        <img :src="item.userAvatar">
                        <p>{{item.content}}</p>
                        <i v-show="item.barrageType === 64"></i>
                    </div>
                </div>
        </div>

trumpet-item 为弹幕 如果接收到消息就往list里push,push前先判断当前跑道能不能插入弹幕,确保当前弹幕不会和上一条弹幕重叠,如果不能(即当前跑道有一条弹幕正在移动),则把当前弹幕插入下一条弹幕跑道里(我这里一共设了四条跑道),下面是方法:
注:我这边定义的是弹幕在屏幕上移动的时长是6s,弹幕移动动画用的是translate
首先是先把从云信接收的消息体obj整理成自己想要的格式

        formatObj(obj){
            let width = this.textSize(14,obj.content)>70?this.textSize(14,obj.content)+70:140//元素的宽度
            let boxWidth = document.getElementsByClassName('center')[0].offsetWidth //屏幕宽度
            let speed = (width+boxWidth)/6   //弹幕速度
            obj.second = (width/speed).toFixed(1)*1000 //元素插入需要的时间
            obj.startTime =  Date.now() //元素动画开始的时间
            obj.endTime =  obj.startTime+6000+obj.second //元素动画结束的时间
            obj.trumpetItemShow = true
            let style = document.styleSheets[0];
            let transformWidth = width+boxWidth;
            transformWidth = (Math.ceil(transformWidth))%2 ==0 ? Math.ceil(transformWidth) :Math.ceil(transformWidth)+1 //防止字体模糊
            style.insertRule("@keyframes bounce-in{from{ transform: translateX(0); }to{ transform: translateX(-"+transformWidth+"px);}}",1);//写入样式
            return obj
        },
        textSize(fontSize, text) { //根据文本内容获取元素宽度
            let span = document.createElement("span");
            span.innerText = text
            span.style.visibility = "hidden";
            span.style.fontSize = fontSize+'px';
            span.style.id = 'fakeSpan';
            document.getElementsByClassName("center")[0].appendChild(span);
            let newWidth = span.offsetWidth;
            document.getElementsByClassName("center")[0].removeChild(span);
            return newWidth;
        }

上面的方法的作用是
计算出并记录下
1.弹幕从屏幕左边出现到完全出现需要的时间
2.弹幕插入动画开始的时间(在屏幕左边出现前一秒)
3弹幕动画结束的时间(在屏幕右边消失的后一秒)
用于判断↓

 //判断当前弹幕是否能插入跑道
        getTrack(val){   //val是格式化好的弹幕
            let obj =  _.cloneDeep(val)
            for(let i = 0;i<this.list.length;i++){ //遍历四条跑道
                let lastChatData = this.list[i][this.list[i].length-1]  //当前跑道最后一条数据
                if(this.list[i].length==0){  //如果是当前跑道的第一条数据 直接插入跑道
                    this.list[i].push(this.formatObj(obj))
                    return
                }
                if(Date.now()-lastChatData.startTime>lastChatData.second){  //如果不是当前跑道的第一条数据 过了等待时间插入跑道
                    this.list[i].push(this.formatObj(obj))
                    return
                } 
            }
            //都不是则进入等待队列
            this.toWait.push(obj)   
        },

this.toWait 是等待队列 ,在所有跑道都有弹幕在插入的时候,新的弹幕消息进入等待队列,然后定时询问是否有跑道能插入数据 ,我这里使用的是watch

    watch:{
        YxLiveRoomBarrageVo(val){ //接收到消息的时候判断是否能插入弹幕
            this.getTrack(val)
        },
        toWait(newVal){ //等待队列有值得时候定时询问是否能插入弹幕
            if(newVal.length>0){
                this.timer = setInterval(()=>{
                    for(let item of newVal){
                        this.getTrack(item)
                        this.toWait.shift()
                    }
                }, 500)
            }else{
                this.timer && clearInterval(this.timer)
            }
        },
        list(newVal){
            this.list.forEach((val,index)=>{
                if(val.length>=20){
                    this.delectItem(val)
                }
            })
        }
    },

list是我的四条跑道

data(){
        return {
            list:[[],[],[],[]],
            timer:null,
            timer1:null,
            toWait:[] //等待插入的弹幕
        }
    },

监听它是为了定时清理数据 ,每条跑道的弹幕数据大于20的时候清理一次,
清理的方法是

        delectItem(arr){ //定时清除
            for(let i = 0;i<arr.length;i++){
                if(arr[i].endTime<Date.now()){
                    arr[i].trumpetItemShow = false
                }
            }
        },

所以上面的endTime是用来判断但是是不是已经完成动画了,完成了的弹幕就能清理掉,最后

    destroyed() {
        this.timer && clearInterval(this.timer)
        this.timer1 && clearInterval(this.timer1)
    }

清一下定时器


成果.jpg

相关文章

  • vue 直播弹幕功能

    需求是不重叠弹幕公司使用的是云信接发消息,我的思路是给直播间四条弹幕跑道,接收到弹幕之后往跑道内插入弹幕以下是其中...

  • 百万在线的美拍直播弹幕系统的实时推送技术实践之路

    1、内容概述 直播弹幕是直播系统的核心功能之一。如何迅速作出一个有很好扩展性的弹幕系统?如何应对业务迅速发展?相信...

  • 你看视频开弹幕么?

    最近在各大视频,直播网站几乎同时因为技术原因停止了弹幕功能。作为习惯了开弹幕看视频的我来说,没有弹幕的那几天还真是...

  • iOS 弹幕效果思路(自己写一个弹幕)

    当遇到有直播功能的时候,第一时间也会想到弹幕功能,那么,弹幕功能又是怎么实现的呢?下面是我的实现思路,如果有更好的...

  • Python实现直播弹幕自动发送

    前言 今天制作的这一款弹幕机器人,是能在B站能指定直播间、自动发弹幕的功能因为没做那么多的功能,所以代码很简单,适...

  • 直播中 BarrageRenderer 弹幕的显示

    直播中BarrageRenderer弹幕的显示(一)—— 框架介绍直播中BarrageRenderer弹幕的显示(...

  • IQKeyboardManager的bug

    这个bug是这样的,在首页点cell会进入到直播间页面,直播间有一个发弹幕的功能,textView点击整个直播页面...

  • vue, js写一个手持弹幕

    两天时间用vue写一个手持弹幕,(没有完成所有功能) 先看一下效果 这里使用vue 写的,只支持vue语法。后期有...

  • iOS 弹幕效果

    项目中视频直播有个弹幕功能,网上也有很多弹幕的demo,之前忙于项目进度,没有细致研究其中是如何实现的。如今闲暇之...

  • 直播项目开发记录-(1)项目需求

    项目组要包括几个功能模块: 1.直播模块 直播模块包括直播视频流的播放,即时通讯聊天室,弹幕等,并且直播后的视频源...

网友评论

      本文标题:vue 直播弹幕功能

      本文链接:https://www.haomeiwen.com/subject/ygyqshtx.html