IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    如何实现弹幕效果? · 看不见我的美 · 是你瞎了眼

    馬腊咯稽发表于 2020-04-20 00:00:00
    love 0
    如何实现弹幕效果?

    数据格式

    弹幕一般用在直播或者视频播放的场景中,是评论的一种变形;按照我的理解,它的数据格式应该是:

    1
    2
    3
    4
    5
    
    {
     [时间戳/视频对应的秒数]: [对应时间点的弹幕列表],
     31415926: [{name: "张三", content: "哈哈哈哈哈"}, {}, {}...],
     ...
    }
    

    发布弹幕

    当用户发布弹幕时,获取当前视频的时间点,将弹幕插入到弹幕列表中:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    addBarrage = () => {
     let barrage = inputEle.value;
     if (barrage && barrage.trim().length > 0) {
     let now = this.getCurrentTime();
     let content = barrage.trim();
     if (this.barrages[now]) {
     this.barrages[now].push({
     name: '麻辣个鸡', // 当前用户的用户名
     content
     });
     } else {
     this.barrages[now] = [
     {
     name: '麻辣个鸡',
     content
     }
     ];
     }
     inputEle.value = '';
     }
    };
    

    弹幕展示

    实时获取视频的播放状态,当视频播放时,获取视频播放位置;当播放时间等于弹幕时间时,展示对应弹幕:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    // 这个函数要放到计时器里执行
    appendBarrage = () => {
     let list = this.barrages[this.getCurrentTime()] || null;
     if (Array.isArray(list)) {
     list.forEach((item, index) => {
     this.id = this.id + 1;
     let id = this.id;
     let node = this.generateSpan(item, index, id); // 生成每条弹幕的容器
     sectioner.append(node);
     // 弹幕最短的运动长度就是视频窗口宽度加上弹幕本身的长度了
     let temp = document.querySelector(`[data-id="${id}"]`);
     let where = temp.dataset.where;
     // 使用 transform 性能比较好
     temp.style.transform = `translate3D(-${temp.clientWidth}px, ${
     where * 20
     }px, 0)`;
     // 当弹幕弹出屏幕时,可将弹幕移除 DOM 提升性能
     temp.addEventListener(
     'transitionend',
     function () {
     this.remove(true);
     },
     { once: true }
     );
     });
     }
    };
    

    怎么展示弹幕呢?可以根据视频的高度和弹幕的高度,设置相应的弹幕轨道:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    // 计算轨道数
    setFloors = () => {
     this.floor = Math.floor(videoEle.clientHeight / 20) - 1;
    };
    generateSpan = (item, index, id) => {
     let where = 0;
     let span = document.createElement('span');
     where = this.where;
     // 分层摆放每条弹幕
     if (this.where > this.floor - 1) {
     this.where = 0;
     } else {
     this.where++;
     }
     span.innerText = `${item.name}: ${item.content}`;
     span.dataset.id = `${id}`;
     span.dataset.where = `${where}`;
     span.style.zIndex = `${index}`;
     span.style.transform = `translate3D(${videoEle.clientWidth}px, ${
     where * 20
     }px, 0)`;
     return span;
    };
    

    未完待续

    DEMO 在 这里 ,暂停视频时当前时间对应的弹幕停止滚动还没想好怎么实现(初步想法是使用 animation 替换 transform,因为 animation-play-state 可以控制动画的状态)。



沪ICP备19023445号-2号
友情链接