当前位置: 首页 > news >正文

为什么B站中的弹幕可以不遮挡人物

上班逛B站时摸鱼时,看到了满屏的弹幕,而且还不挡脸,突然心血来潮来看看它是怎么实现的?
在这里插入图片描述

不难发现弹幕其实它就是有一个蒙版层div,遮挡在视频组件的上方,z-index层级设置的比较高(这里是11),video标签层级为默认值0,所以这个视频播放的页面是由多个层组成的(当然该页面还有很多其他的layout层,这里不细讲),这一点我们也可以从页面layout分层中也可以直观地看出来:

、

此时又有同学跳出来问。。。。。。
在这里插入图片描述
同学A: ”那它这个不挡脸的弹幕又是如何实现的呢?“

me:这位同学这个问题很好,我们接着看:

me:高端的食材往往需要最崴的厨子 不对… 高端的效果,往往底层原理很简单
废话不多说,我模拟了一个Demo,直接上代码。。。

// index.html文件
<head><meta charset="utf-8" /><link rel="icon" href="%PUBLIC_URL%/favicon.ico" /><meta name="viewport" content="width=device-width, initial-scale=1" /><meta name="theme-color" content="#000000" /><metaname="description"content="Web site created using create-react-app"/><title>React App</title><style>.back{position: relative;width: 751px;height: 420px;-webkit-mask-image: url('data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKIHdpZHRoPSI3NTAuMjIyMjIyMjIyMjIyMnB4IiBzdHlsZT0idHJhbnNmb3JtOnNjYWxlKDEuMDAxLDEpOyIgaGVpZ2h0PSI0MjJweCIgdmlld0JveD0iMCAwIDMyMC4wMDAwMDAgMTgwLjAwMDAwMCIKIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIG1lZXQiPgo8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjAwMDAwMCwxODAuMDAwMDAwKSBzY2FsZSgwLjEwMDAwMCwtMC4xMDAwMDApIgpmaWxsPSIjMDAwMDAwIiBzdHJva2U9Im5vbmUiPgo8cGF0aCBkPSJNMCA5MDUgbDAgLTg5NSAyMzggMCAyMzggMCAyIDYzIGM1IDEzNiA0NiAzNTcgNzggNDE3IDIyIDQzIDU2IDc1IDE0NCAxMzUgOTYKNjUgMTI1IDg3IDE3OCAxMzEgMjAgMTcgNjUgNTAgOTggNzMgbDYxIDQxIDcgNzIgYzMgNDAgOSA5MSAxMiAxMTQgNSAzNyAxIDQ4Ci00MCAxMDggLTI1IDM3IC00NiA3NCAtNDYgODIgMCA4IC0xMSAxOSAtMjQgMjMgLTI4IDExIC0zNiAyOSAtMzYgODAgMCAyMCAtNgo0NSAtMTMgNTYgLTcgMTEgLTIwIDQ2IC0yNyA3OCAtMjQgMTA0IDIwIDIwMSAxMTMgMjQ4IDI4IDE1IDM3IDI2IDM3IDQ0IGwwCjI1IC01MTAgMCAtNTEwIDAgMCAtODk1eiIvPgo8cGF0aCBkPSJNMTU5MCAxNzc5IGMwIC0xMiA3IC0yNyAxNyAtMzQgOSAtNyAxOSAtMzQgMjMgLTYxIDQgLTI3IDE0IC02MyAyMSAtODEgMTAKLTI0IDEwIC00MCAyIC03MCAtMTkgLTY2IC00MyAtMTg3IC00MyAtMjE4IC0xIC0yNyAtNDcgLTIwNiAtNjQgLTI0NiAtNiAtMTMKOSAtMjMgNzMgLTQ5IDEwMSAtNDAgMTA4IC00OCA5MSAtMTAxIC0xNiAtNDYgLTEyIC01MiA1MSAtNjkgMzcgLTEwIDEyMyAtNTMKMTQ4IC03MyAyNiAtMjEgODYgLTExMSAxMTkgLTE3NSAyNiAtNTIgMzIgLTc2IDMyIC0xMjcgMCAtNTkgMyAtNjYgNDEgLTExMQoyMiAtMjcgNDcgLTYyIDU2IC03OSA5IC0xNiAzNSAtNTkgNTggLTk1IDQ5IC03NiA4MyAtMTUwIDc3IC0xNjggLTMgLTkgOTIKLTEyIDQ1MiAtMTIgbDQ1NiAwIDAgODk1IDAgODk1IC04MDUgMCAtODA1IDAgMCAtMjF6Ii8+CjwvZz4KPC9zdmc+Cg==');-webkit-mask-size: 751px 420px;background-color: brown;}.bullet{position: absolute;font-size: 20px;color: #FFFFFF;}</style></head><body><div id="root">23456789</div></body>
</html>
// App.js文件
import Img from './components/video';function App() {return <Img />;
}export default App;
// Img组件
const texts=[{left:140,top:10,text:'UP主好帅'},{left:200,top:430,text:'你难道就是传说中的奶灵'},{left:231,top:70,text:'你好,我是ronychen'},{left:20,top:35,text:'喜欢唱跳rap篮球'},{left:821,top:53,text:'HELLO WORLD'},{left:30,top:121,text:'我是练习时长2年半的练习生'},{left:398,top:321,text:'哈哈哈哈'},{left:190,top:90,text:'我就蹭蹭,不进去'},{left:170,top:200,text:'hahahahahahahahah'},{left:240,top:490,text:'这是什么XXXX'},{left:420,top:340,text:'元芳,你则么看?'},
]
const Img =()=>{return (<div className='back'>{texts.map((item,index)=>(<div key={index} className="bullet" style={{left:`${item.left}px`, top:`${item.top}px`}}>{item.text}</div>))}</div>)
}export default Img;

基本看到这,大部分同学应该都能理解了,其实原理很简单,一张蒙版图 + 一个属性(-webkit-mask-image)就搞定了,实际效果就是这样:
在这里插入图片描述
是不是有种那感觉了

总结
弹幕原理:就如我上面所说,有一个单独的蒙版层div,它会设置一个比视频组件更高的层级值,这样就能显示在视频上方,这里插一句话,在移动端,大多数浏览器貌似都不支持在video标签上放其他内容,在移动端,video标签貌似已经脱离标准文档流,即使你设置再高的z-index值也是不行的,回归主题,至于弹幕不遮挡人物这种效果的实现,我的理解应该是AI算法会实时导出视频中识别到的人物,然后导出这些人物的图片,这点我们可以在network中看到会有实时的图片加载,这些图片就是我们上面要用到的蒙版图,然后再结合css中的-webkit-mask-image属性,就可以实现上述效果,该属性具体的用法可以点击这里查看

至于这一张张的蒙版图片是怎么来的,这块我也不是很清楚,应该是AI算法实时导出的吧! 有兴趣的同学自行了解吧 hahaha。。。

在这里插入图片描述

相关文章:

为什么B站中的弹幕可以不遮挡人物

上班逛B站时摸鱼时&#xff0c;看到了满屏的弹幕&#xff0c;而且还不挡脸&#xff0c;突然心血来潮来看看它是怎么实现的&#xff1f; 不难发现弹幕其实它就是有一个蒙版层div&#xff0c;遮挡在视频组件的上方&#xff0c;z-index层级设置的比较高&#xff08;这里是11&…...

数据结构 第八章 查找(静态查找表)

集合 1、集合中的数据元素除了属于同一集合外,没有任何的逻辑关系 2、在集合中,每个数据元素都有一个区别于其他元素的唯一标识(键值或者关键字值) 3、集合的运算&#xff1a; 1 查找某一元素是否存在(内部查找、外部查找) 2 将集合中的元素按照它的唯一标识进行排序4、集合的…...

【Python基础】数据类型(元组、列表)

文章目录二. 数据类型2.1 元组 tuple2.1.1 定义特性2.1.2 拼接拷贝2.1.3 元组拆包2.1.4 元组方法 count2.2 列表 list2.2.1 基础定义2.2.2 增删操作2.2.3 连接联合2.2.4 其他常规操作2.2.5 列表推导式2.2.6 生成器表达式2.x 小结&#xff1a;何时使用元组或列表二. 数据类型 Py…...

你了解互联网APP搜索和推荐的背后逻辑么?

1.搜索和推荐无处不在我们习惯了百度、Google、360搜索的便捷&#xff0c;输入你想要搜索的关键词&#xff0c;立马呈现给你一批对应的结果&#xff0c;供你筛选。我们也经常上淘宝、京东、拼多多购物&#xff0c;输入想买的商品&#xff0c;瞬间列出一页一页的商品清单供我们选…...

Bug的级别,按照什么划分

Bug分类和定级一、bug的定义二、bug的类型三、bug的等级四、bug的优先级一、bug的定义一般是指不满足用户需求的则可以认为是bug&#xff0c;狭义指软件程序的漏洞或缺陷&#xff0c;广义指测试工程师或用户提出的软件可改进的细节、或与需求文档存在差异的功能实现等对应三个测…...

微服务项目简介

项目简介 项目模式 电商模式&#xff1a;市面上有5种常见的电商模式&#xff0c;B2B、B2C、 C2B、 C2C、O2O; 1、B2B模式 B2B (Business to Business)&#xff0c;是指 商家与商家建立的商业关系。如:阿里巴巴 2、B2C 模式 B2C (Business to Consumer), 就是我们经常看到的供…...

SLAM中坐标轴旋转及ros的接口解释

读完几个loam算法&#xff0c;满篇的坐标轴旋转&#xff0c;还是手写的(作者&#xff0c;用eigen写不好嘛。。。)&#xff0c;我滴天适应了好久…&#xff0c;今天就总结一下坐标轴旋转问题。 一、首先&#xff0c;我们看一下ros中关于欧拉角旋转的函数&#xff1a;setRPY、set…...

文件管理(9)

文件管理 0 引言 为什么要引入文件系统&#xff1f; 信息管理的需要&#xff1a;用户面前提供一种规格化的机制&#xff0c;方便用户对文件的存取、提高效率。操作系统本身需要–操作系统本身也不是常驻内存的&#xff0c;也有大量的信息需要存于外存。 1 文件定义 文件&a…...

PyTorch学习笔记:nn.TripletMarginLoss——三元组损失

PyTorch学习笔记&#xff1a;nn.TripletMarginLoss——三元组损失 torch.nn.TripletMarginLoss(margin1.0, p2.0, eps1e-06, swapFalse, size_averageNone, reduceNone, reductionmean)功能&#xff1a;创建一个三元组损失函数(triplet loss)&#xff0c;用于衡量输入数据x1,x…...

冒泡排序详解

冒泡排序是初学C语言的噩梦&#xff0c;也是数据结构中排序的重要组成部分&#xff0c;本章内容我们一起探讨冒泡排序&#xff0c;从理论到代码实现&#xff0c;一步步深入了解冒泡排序。排序算法作为较简单的算法。它重复地走访过要排序的数列&#xff0c;一次比较两个元素&am…...

git极快上手指南超级精简版

注&#xff1a;本文参考https://www.liaoxuefeng.com/wiki/896043488029600 原文非常值得一读&#xff0c;作者学识渊博&#xff0c;补充了很多有意思的知识。我仅仅是拾人牙慧。 git是最先进的分布式版本控制系统。 版本控制系统——自动记录系统中文件的改动情况&#xff0…...

蓝桥杯-最长公共子序列(线性dp)

没有白走的路&#xff0c;每一步都算数&#x1f388;&#x1f388;&#x1f388; 题目描述&#xff1a; 已知有两个数组a,b。已知每个数组的长度。要求求出两个数组的最长公共子序列 序列 1 2 3 4 5 序列 2 3 2 1 4 5 子序列&#xff1a;从其中抽掉某个或多个元素而产生的新…...

GO的并发模式Context

GO的并发模式Context 文章目录GO的并发模式Context一、介绍二、Context三、context的衍生四、示例&#xff1a;Google Web Search4.1 server程序4.2 userip 包4.3 google 包五、使用context包中程序实体实现sync.WaitGroup同样的功能&#xff08;1&#xff09;使用sync.WaitGro…...

《Redis实战篇》六、秒杀优化

6、秒杀优化 6.0 压力测试 目的&#xff1a;测试1000个用户抢购优惠券时秒杀功能的并发性能~ ①数据库中创建1000用户 这里推荐使用开源工具&#xff1a;https://www.sqlfather.com/ &#xff0c;导入以下配置即可一键生成模拟数据 {"dbName":"hmdp",…...

《C++ Primer Plus》第16章:string类和标准模板库(11)

其他库 C 还提供了其他一些类库&#xff0c;它们比本章讨论前面的例子更为专用。例如&#xff0c;头文件 complex 为复数提供了类模板 complex&#xff0c;包含用于 float、long 和 long double 的具体化。这个类提供了标准的复数运算及能够处理复数的标准函数。C11 新增的头文…...

声明和定义

前言 很多编程语言的语法中都有关于声明和定义的概念&#xff0c;这种概念一般会应用于函数或变量的创建和使用中&#xff0c;但是为什么要这么做&#xff1f; 以C语言为例&#xff0c;一些书籍或教程会要求读者在程序文件开头写上函数和变量的声明&#xff0c;然后再在后面对…...

Python获取最小路径,查找元素在list中的坐标

# codingutf-8__author__ Jeff.xiedef t(li):pass获取最小路径def minPathSum(grid):if not grid:return 0m len(grid) #m列n len(grid[0]) #n行print(grid[0])print("m: ",m)print("n: ",n)#创建一个二维数组dp [[0]*n for _ in range(m)]print(dp) #这…...

数据采集协同架构,集成马扎克、西门子、海德汉、广数、凯恩帝、三菱、海德汉、兄弟、哈斯、宝元、新代、发那科、华中各类数控以及各类PLC数据采集软件

文章目录 前言一、采集协同架构是什么&#xff1f;可以做什么&#xff08;数控、PLC配置采集&#xff09;&#xff1f;二、使用步骤 1.打开软件&#xff0c;配置MQTT或者数据库&#xff08;支持sqlserver、mysql等&#xff09;存储转发消息规则2.配置数控系统所采集的参数、转…...

Allegro172版本如何用自带的功能实现快速在1MMBGA下方等距放置电容

Allegro172版本如何用自带的功能实现快速在1MMBGA下方等距放置电容 在做PCB设计的时候,在1MM中心间距的BGA背面放置电容,是非常常见的设计,如何快速把电容等距放在BGA下方,除了借助辅助工具外,在Allegro升级到了172版本的时候,可以借助本身自带的功能实现快速放置,以下图…...

一种简单的统计pytorch模型参数量的方法

nelememt()函数Tensor.nelement()->引自Tensor.numel()->引自torch.numel(input)三者的作用是相同的Returns the total number of elements in the inputtensor.返回当前tensor的元素数量利用上面的函数刚好可以统计模型的参数数量parameters()函数Module.parameters(rec…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...