zl程序教程

您现在的位置是:首页 >  Java

当前栏目

以《铁山靠》为例!讲解为什么 B 站的弹幕可以不挡人物?

2023-02-18 15:49:53 时间

大家好,我是阿潘

今天来分享一个实战的教程哈

目标:复现 b 站视频中出现人物时,弹幕不会遮挡人物的效果

相信经常刷 b 站视频的小伙伴,应该能注意到网友发的弹幕遇到人物时,并不会遮挡住人。

其实大部分一眼就能想到这个背后的技术大概是如何实现的

例如:画面肯定将人物区域截取出来,将人设置在最顶层,弹幕经过人体的时候,不要覆盖到

那么我们也去复现一下这个效果吧

查看页面背后是如何实现的

假设你使用的谷歌浏览器,打开一个弹幕比较多的 《鸡你太美》 艺术作品。

F12 查看网页的源码,在element 栏目下 ctrl + f ,并输入 -webkit-mask-image 回车两次即可看到下图的页面(如果没有找到,可以尝试换其他浏览器,没有找到规律的时候可以多看几次)

可以看到标红的框内,在最左边的框里面已经出现了知名舞蹈动作 《铁山靠》

此时可以直接把值复制出来(当然也可以选择另存到本地):

data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKIHdpZHRoPSI2NjhweCIgc3R5bGU9InRyYW5zZm9ybTpzY2FsZSgxLDEuMDAxKTsiIGhlaWdodD0iMzc1Ljc1cHgiIHZpZXdCb3g9IjAgMCAzMjAuMDAwMDAwIDE4MC4wMDAwMDAiCiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCBtZWV0Ij4KPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsMTgwLjAwMDAwMCkgc2NhbGUoMC4xMDAwMDAsLTAuMTAwMDAwKSIKZmlsbD0iIzAwMDAwMCIgc3Ryb2tlPSJub25lIj4KPHBhdGggZD0iTTAgOTA1IGwwIC04OTUgNTA2IDAgYzQwMCAwIDUwNSAzIDUwMSAxMyAtMiA2IDUgMjcgMTYgNDYgMTcgMjkgMjEgNTUgMjQgMTQ5CjYgMjM0IDM3IDM0MiAxMzAgNDU2IDI2IDMyIDY0IDg4IDgzIDEyNSBsMzUgNjYgLTcyIDc3IGMtNDAgNDMgLTczIDg0IC03MyA5MgowIDE4IDY0IDk5IDEyMyAxNTggNDQgNDIgMTQ1IDEwMCAyMDAgMTEyIDIzIDUgMjcgMTEgMjcgNDEgMCAyNyA3IDM5IDMzIDU5CjM4IDI5IDUzIDMxIDEwOSAxNCA0MyAtMTMgODggLTU4IDg4IC04OSAwIC0xMSAtOSAtNDAgLTIwIC02NSAtMjIgLTQ4IC0yMAotNzEgMTEgLTExNCAxNSAtMjAgMjAgLTQ2IDIyIC0xMzUgMiAtMTAwIDAgLTExNCAtMjMgLTE2MCAtMTcgLTM0IC0zMyAtNTEKLTUwIC01NiAtMjEgLTUgLTI1IC0xMCAtMjIgLTM5IDEgLTE5IDExIC00NCAyMiAtNTUgMTAgLTExIDM1IC02MSA1NSAtMTEwIDIwCi01MCA0MyAtMTAzIDUyIC0xMjAgMjcgLTU0IDYyIC0xNzYgNzQgLTI1OSA2IC00NCAyMCAtMTAzIDMwIC0xMjkgMTAgLTI3IDE1Ci01NSAxMiAtNjMgLTQgLTEyIDg5IC0xNCA2NTEgLTE0IGw2NTYgMCAwIDg5NSAwIDg5NSAtMTYwMCAwIC0xNjAwIDAgMCAtODk1eiIvPgo8cGF0aCBkPSJNMTM1OCA1ODIgYy0yNiAtMTUgLTc0IC01MyAtMTA3IC04NCAtNTMgLTUxIC02MCAtNjMgLTcwIC0xMTUgLTIyIC0xMTcgLTMxCi0xNTkgLTQxIC0yMDggLTggLTM2IC04IC01OSAtMSAtNzkgNiAtMTUgMTEgLTQxIDExIC01NyBsMCAtMjkgMzIwIDAgMzIwIDAgMAo1MCBjMCAzNiAtMTMgODQgLTQ2IDE2NyAtMjUgNjUgLTUwIDEyOSAtNTUgMTQ0IC02IDE0IC01NiA3MyAtMTEyIDEzMiAtMTE3CjEyMyAtMTM0IDEyOSAtMjE5IDc5eiIvPgo8L2c+Cjwvc3ZnPgo=

另存到本地,只需选择 network --> name (找 data:image/svg) --> preview --> 出现的图片右键另存即可

PS:这里证明大家的猜想是对的,后台的页面处理确实添加了对人物区域进行特殊操作。

同时注意到这个样式的 css 属性: -webkit-mask-image(实现的功能:To apply a mask over an image.)

复现效果

整体实现思路:

1、将 mask 保存到本地 或者 将图片的base64编码保存

2、将原图保存,这里我没有找到,所以直接截图下来了

3、将原图、弹幕和mask 组合起来

如果是将图片下载到本地 把 -webkit-mask-image: url() 中的值换成 图片路径即可

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    .video {
      width: 668px;
      height: 376px;
      position: relative;
      background-color: black;
      -webkit-mask-image: url("data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKIHdpZHRoPSI2NjhweCIgc3R5bGU9InRyYW5zZm9ybTpzY2FsZSgxLDEuMDAxKTsiIGhlaWdodD0iMzc1Ljc1cHgiIHZpZXdCb3g9IjAgMCAzMjAuMDAwMDAwIDE4MC4wMDAwMDAiCiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCBtZWV0Ij4KPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsMTgwLjAwMDAwMCkgc2NhbGUoMC4xMDAwMDAsLTAuMTAwMDAwKSIKZmlsbD0iIzAwMDAwMCIgc3Ryb2tlPSJub25lIj4KPHBhdGggZD0iTTAgOTA1IGwwIC04OTUgNzA4IDAgNzA3IDAgMSAxNTMgYzAgODMgNCAxODUgOCAyMjUgNyA2NyA2IDcyIC0xMiA3MiAtMTEgMAotMjUgNyAtMzIgMTUgLTcgOCAtMTggMTUgLTI1IDE1IC0xOSAwIC0yNiAyNiAtMzIgMTEwIC0zIDQ5IC0xNSAxMDEgLTM0IDE0OQotMTYgNDAgLTI5IDg3IC0yOSAxMDMgMCAzNCA1NSAxNDcgNzUgMTU1IDggMyAxNSAxNSAxNSAyNyAwIDI1IDYxIDE1NiA5MSAxOTUKMTEgMTQgMzggNDAgNjAgNTggNDYgMzcgOTkgMTA5IDk5IDEzNyAwIDExIC02IDI3IC0xNCAzNSAtMjYgMzAgLTg2IDE1MyAtODYKMTc3IDAgMTMgMTYgNDEgMzYgNjQgbDM2IDQwIDEwNCAwIDEwNCAwIDM4IC0zNCBjMzIgLTMwIDM3IC00MCAzNiAtNzggLTEgLTI1Ci0xMiAtNjQgLTI3IC05NCAtMjUgLTUwIC0yNSAtNTAgLTcgLTkxIDEzIC0yOSAzNiAtNTMgNzcgLTgxIDE0NyAtMTAxIDIyNgotMjQzIDI0MCAtNDI4IDcgLTEwMiAtNiAtMTQ4IC01MCAtMTcwIC01NiAtMjggLTY3IC00NCAtNjcgLTkxIDAgLTUwIC0yMSAtOTcKLTUwIC0xMTMgLTE4IC0xMCAtMjAgLTIxIC0yMCAtMTQ1IDAgLTk3IC01IC0xNTYgLTIwIC0yMTcgLTEwIC00NiAtMjIgLTEwNwotMjYgLTEzNSBsLTcgLTUzIDY1MiAwIDY1MSAwIDAgODk1IDAgODk1IC0xNjAwIDAgLTE2MDAgMCAwIC04OTV6Ii8+CjwvZz4KPC9zdmc+Cg==") ;
      -webkit-mask-size: 668px 376px;
    }
    .bullet {
      position: absolute;
      font-size: 20px;
      color: white;
      animation: ani 5s linear infinite;
    }
    .showBullet {
      position: absolute;
      font-size: 20px;
      color: red;
      animation: show 5s linear infinite;
    }

    @keyframes ani {
      0% {
        transform: translateX(668px);
      }
      100% {
        transform: translateX(-668px);
      }
    }

    @keyframes show {
      0% {
        opacity: 0;
      }
      10% {
        opacity: 1;
      }
      100% {
        opacity: 1;
      }
    }
</style>
</head>
<body>
<div class="video">
  <div class="bullet" style="left: 100px; top: 120px;">鸡你太美,鸡你太美</div>
  <div class="bullet" style="left: 200px; top: 60px;">小黑子,哥哥下蛋你别吃</div>
  <div class="bullet" style="left: 500px; top: 60px;">食不食油饼</div>
  <div class="bullet" style="left: 300px; top: 140px;">鸡哥</div>
  <div class="bullet" style="left: 400px; top: 100px;">铁山靠</div>
  <div class="showBullet" style="left: 320px; top: 20px;">完结撒花</div>
  <div class="showBullet" style="left: 340px; top: 50px;">泪目</div>
</div>
</body>
</html>

声明,我对前端了解并不多,只了解一点基础,如果有误,欢迎指正。下面是我的一点浅薄的认识。

上面的 html 实现的功能

1、首先看下 body 部分,定义文档的主体。body 里面包含了一个 video 属性的 div (区域)

2、 div 的属性是 video,所以查看一下上面的 .video ,里面定义了 区域的宽高、背景色以及将人物区域遮挡住的 -webkit-mask-image

<div> 标签定义 HTML 文档中的一个分隔区块或者一个区域部分

3、div 内部嵌套的 div 属性 bullet、showBullet,用于显示弹幕

综合起来就是上面 html 创建了一个区域,区域的背景黑色,并将中间的人物区域遮挡(mask)掉,这样子弹幕不会在创建的区域上,以实现弹幕不遮挡人物的效果。

效果是这样的:

最后将原始图片添加到画面中

至此,我们就实现了 B 站同款的不遮挡人物的弹幕。

PS:html 文件打开方式选择浏览器即可查看到上图效果

参考资料

https://juejin.cn/post/7141012605535010823

https://blog.csdn.net/qq_37669585/article/details/126829000