vue 直播弹幕功能

需求是不重叠弹幕
公司使用的是云信接发消息,我的思路是给直播间四条弹幕跑道,接收到弹幕之后往跑道内插入弹幕
以下是其中一条弹幕跑道的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
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 版本记录 前言 在我们做直播等视频类app的时候,总是有显示和发送弹幕的要求,弹幕可以方便用户进行沟通和互动,增加...
    刀客传奇阅读 4,863评论 8 16
  • 重点参考链接: View Programming Guide for iOS https://developer....
    Kevin_Junbaozi阅读 4,289评论 0 15
  • 那一夜,她依偎在我怀里,问我,你有什么理想。 我以为云雨过后的女生都会问,你爱我么?这种傻逼问题,愣是没想到她竟然...
    乄清玄阅读 282评论 0 0
  • 闹钟定了6个,其实第一个开始响的时候我就已经醒了,醒来第一件事先是打开手机刺激眼部神经,翻看微信和其他软件的消息,...
    钺冥阅读 381评论 0 4
  • 三月,早樱已经盛开 你走在河边上,欣赏春光 一棵柳树垂下万千柳条 静静的发芽 河里有一条蓝色的船 在水中荡来荡去 ...
    叶落心阅读 238评论 0 2