fly-barrage 前端弹幕库(5):高级弹幕的设计与实现

项目官网地址:https://fly-barrage.netlify.app/;
👑🐋🎉如果感觉项目还不错的话,还请点下 star 🌟🌟🌟。
Gitee:https://gitee.com/fei_fei27/fly-barrage(Gitee 官方推荐项目);
Github:https://github.com/feiafei27/fly-barrage;

其他系列文章:
fly-barrage 前端弹幕库(1):项目介绍
fly-barrage 前端弹幕库(2):弹幕内容支持混入渲染图片的设计与实现
fly-barrage 前端弹幕库(3):滚动弹幕的设计与实现
fly-barrage 前端弹幕库(4):顶部、底部弹幕的设计与实现

高级弹幕的计算是最简单的,因为每个高级弹幕和其他弹幕是无交互的,不需要处理相互重叠的问题,只需要根据当前视频的播放时间计算出高级弹幕处于的位置即可。

1:相关类型

/*** 用于描述高级弹幕*/
export default class SeniorBarrage extends BaseBarrage {constructor(seniorBarrageOptions: SeniorBarrageOptions, barrageRenderer: BarrageRenderer) {}
}export type SeniorBarrageOptions = BaseBarrageOptions & {// 弹幕的类型barrageType: 'senior';// 高级弹幕配置seniorBarrageConfig: SeniorBarrageConfig;
}/*** 用于描述二位平面中的一点(单位 px)*/
export type Location = {x: number;y: number;
}/*** 用于描述二位平面中的一点(面向用户)*/
export type LocationDefine = Location & {// 定义的类型:直接像素 或 canvas 百分比type?: 'PIXEL' | 'PERCENT';// 在 x、y 定义的基础上进行坐标偏移offsetX?: number;offsetY?: number;
}/*** 用于描述高级弹幕的运动配置*/
export type SeniorBarrageConfig = {// 起始点startLocation: LocationDefine;// 结束点endLocation: LocationDefine;// 生存时间(单位为毫秒)(数据要求:> 0)totalDuration: number;// 延迟时间(单位为毫秒)(数据要求:>= 0)delay: number;// 运动时长(单位为毫秒)(数据要求:>= 0)motionDuration: number;
}

高级弹幕的运动分为三部分:

  • 运动前(此时位置一定是在 startLocation);
  • 运动时(根据运动时间、运动速度以及 startLocation 可以计算出来);
  • 运动完成(此时的位置 endLocation);

2:高级弹幕关键数据的计算

export default class SeniorBarrage extends BaseBarrage {constructor(seniorBarrageOptions: SeniorBarrageOptions, barrageRenderer: BarrageRenderer) {this.calcActualLocation();}/*** 计算关键点的实际坐标*/calcActualLocation() {const { startLocation, endLocation, motionDuration } = this.seniorBarrageConfig;// 计算实际起始点的位置// 计算 actualStartLocationlet actualStartLocationX = (startLocation.type || 'PIXEL') === 'PIXEL' ? startLocation.x : startLocation.x * this.canvasSize.width;let actualStartLocationY = (startLocation.type || 'PIXEL') === 'PIXEL' ? startLocation.y : startLocation.y * this.canvasSize.height;if (startLocation.offsetX) actualStartLocationX += startLocation.offsetX;if (startLocation.offsetY) actualStartLocationY += startLocation.offsetY;this.actualStartLocation = {x: actualStartLocationX,y: actualStartLocationY};// 计算 actualEndLocationlet actualEndLocationX = (endLocation.type || 'PIXEL') === 'PIXEL' ? endLocation.x : endLocation.x * this.canvasSize.width;let actualEndLocationY = (endLocation.type || 'PIXEL') === 'PIXEL' ? endLocation.y : endLocation.y * this.canvasSize.height;if (endLocation.offsetX) actualEndLocationX += endLocation.offsetX;if (endLocation.offsetY) actualEndLocationY += endLocation.offsetY;this.actualEndLocation = {x: actualEndLocationX,y: actualEndLocationY};// 根据实际起始点的位置,计算 vx 和 vythis.vx = (this.actualEndLocation.x - this.actualStartLocation.x) / motionDuration;this.vy = (this.actualEndLocation.y - this.actualStartLocation.y) / motionDuration;}
}

这里根据用户提供的配置计算出起始点以及结束点的实际坐标,并根据 运动路程 / 运动时间 计算出运动速度,这些关键数据是在接下来计算高级弹幕实时位置时需要的。

3:获取当前应该渲染的高级弹幕,并计算渲染位置

/*** 获取当前应该渲染的高级弹幕* @param time 视频播放时间点*/
getRenderSeniorBarrages(time: number): SeniorBarrage[] {// 获取当前能够渲染的高级弹幕const renderSeniorBarrages = this.seniorBarrageInstances.filter(barrage =>// 当前时间大于等于弹幕的出现时间 并且 当前时间小于等于弹幕的结束时间time >= barrage.time &&time <= (barrage.time + barrage.seniorBarrageConfig.totalDuration));// 遍历计算高级弹幕的 top 和 leftrenderSeniorBarrages.forEach(barrage => {const startPoint = barrage.time;const delayEndPoint = startPoint + barrage.seniorBarrageConfig.delay;const motionEndPoint = delayEndPoint + barrage.seniorBarrageConfig.motionDuration;if (time >= startPoint && time <= delayEndPoint) {// delay 时间段内(渲染在开始点即可)barrage.left = barrage.actualStartLocation.x;barrage.top = barrage.actualStartLocation.y;} else if (time >= delayEndPoint && time <= motionEndPoint) {// motion 时间段内// 当前的运动时长const motionTime = time - delayEndPoint;barrage.left = barrage.actualStartLocation.x + motionTime * barrage.vx;barrage.top = barrage.actualStartLocation.y + motionTime * barrage.vy;} else {// 运动结束时间段内(渲染在结束点即可)barrage.left = barrage.actualEndLocation.x;barrage.top = barrage.actualEndLocation.y;}});return renderSeniorBarrages;
}

首先根据弹幕的出现时间和 totalDuration 以及当前的 time 过滤出当前应该渲染的高级弹幕。

然后遍历应该渲染的弹幕,进行渲染位置的计算,在这里,先计算出高级弹幕所处于的运动阶段,如果是运动前的话,弹幕的渲染位置就是上文计算好的 actualStartLocation,然后是运动后的话,弹幕的渲染位置就是上文计算好的 actualEndLocation,如果是运动中的话,可以根据运动时间以及速度计算出运动的偏移量,再将偏移量加上起始点的位置即可计算出弹幕此时应该渲染的位置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/748554.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在iPhone上恢复已删除的微信聊天记录?

你好&#xff0c;我前几天删除了微信聊天记录。有什么办法可以恢复iPhone上已删除的微信聊天记录吗&#xff1f; 有些人每次使用设备时都会遇到在 iPhone 上丢失消息的风险。特别是&#xff0c;由于多种因素&#xff0c;可能会丢失第三方数据&#xff0c;微信消息也是如此。微…

2024Vue高频面试题

前言: Vue 在前端开发领域拥有强劲的发展势头,以下是一些 Vue 的发展趋势: 1.持续增长的用户数量: Vue 作为一款轻量级、易学易用的前端框架,吸引了越来越多的开发者和企业选择使用。其活跃的社区和丰富的资源也促进了用户数量的不断增长。 2.生态系统不断丰富: 随着 V…

五粮液与经销商的猫鼠游戏

赶在315前夕&#xff0c;五粮液选择向拼多多“开炮”。 如果是在往常的日子里&#xff0c;这样的官方声明大概率不会产生太大的波澜。偏偏赶在“打假”的特殊节点&#xff0c;五粮液的发声不但收获了一个个热搜和头条&#xff0c;还用一种比较巧妙的方式影响了部分消费者的判断…

远超预期,特效吹爆!《武庚纪》:建议漫改都按这个标准来!

作为《武庚纪》动画党&#xff0c;听闻要改编成真人电视剧时&#xff0c;最害怕的无非五毛钱特效&#xff0c;流水线仙侠&#xff0c;无脑古偶。但在看过《烈焰》&#xff08;原名&#xff1a;武庚纪&#xff09;之后&#xff0c;不得不感叹一句&#xff1a;“倒也不用这么还原…

【计算机网络篇】计算机网络的性能指标

文章目录 &#x1f354;计算机网络的性能指标&#x1f5c3;️常见的计算机网络性能指标⭐速率⭐带宽⭐吞吐量⭐时延⭐时延带宽积⭐往返时间⭐利用率⭐丢包率 &#x1f50e;总结 &#x1f354;计算机网络的性能指标 计算机网络的性能指标被用来从不同方面度量计算机网络的性能 …

算法的渐进时间复杂度

T(n) = O(F(n)) T(n):Time 渐进时间复杂度 O:正比例关系 F(n):代码执行次数 只要代码执行的次数越来越多 所耗费的时间也就越来越高 常见的5种: O(n^2) O(n logn) O(n) O(logn) O(1):不管重复多少次1次也是这个时间,10次也是这个时间。 时间复杂度排序:由小到…

JAVA22 FFM实战之HelloWorld

前言 JDK22即将发布&#xff0c;Java Foreign Function & Memory API将会退出预览&#xff0c;是时候开始学习一波了。 FFM API介绍 FFM API由两大部分组成&#xff0c;一个是Foreign Function Interface&#xff0c;另一个是Memory API。前者是外部函数接口&#xff0c…

对模型性能进行评估(Machine Learning 研习十五)

在上一篇我们已然训练了一个用于对数字图像识别的模型&#xff0c;但我们目前还不知道该模型在识别数字图像效率如何&#xff1f;所以&#xff0c;本文将对该模型进行评估。 使用交叉验证衡量准确性 评估模型的一个好方法是使用交叉验证&#xff0c;让我们使用cross_val_score…

【820复试】操作系统面试问题

文章目录 1. 什么是程序局部性&#xff0c;为什么会有程序的空间局部性&#xff1f;2.为了实现重定位需要哪些硬件&#xff1f;3.在交互式系统中&#xff0c;非剥夺是不是一个好的策略&#xff1f;why&#xff1f;4.CPU不执行程序的时候干什么&#xff1f;5.死锁是什么&#xf…

机器学习-04-分类算法-02贝叶斯算法

总结 本系列是机器学习课程的系列课程&#xff0c;主要介绍机器学习中分类算法&#xff0c;本篇为分类算法与贝叶斯算法部分。 本门课程的目标 完成一个特定行业的算法应用全过程&#xff1a; 懂业务会选择合适的算法数据处理算法训练算法调优算法融合 算法评估持续调优工程…

MySQL大小写敏感、MySQL设置字段大小写敏感

文章目录 一、MySQL大小写敏感规则二、设置数据库及表名大小写敏感2.1、查询库名及表名是否大小写敏感2.2、修改库名及表名大小写敏感 三、MySQL列名大小写不敏感四、lower_case_table_name与校对规则4.1、验证校对规则影响大小写敏感4.1、验证校对规则影响排序 五、设置字段内…

Selenium控制已运行的Edge和Chrome浏览器——在线控制 | 人机交互(详细启动步骤和bug记录)

文章目录 前期准备1. 浏览器开启远程控制指令&#xff08;1&#xff09;Edge&#xff08;2&#xff09;Chrome 2. 执行python代码&#xff08;1&#xff09;先启动浏览器后执行代码&#xff08;2&#xff09;通过代码启动浏览器&#xff08;3&#xff09;Bug问题记录1&#xff…

蓝桥杯决赛2023 RE CyberChef2

思路很清晰&#xff0c;爆IV 但是题目出的有点屎&#xff0c;六位字符串&#xff0c;62的6次方&#xff0c;要我爆到猴年马月&#xff1f; 就当练习脚本吧 #Cyber2 wp from Crypto.Cipher import DES, AES from Crypto.Util.Padding import pad, unpad key_des b0a0b0c0…

PHP异世界云商系统开源源码

系统更新与修复列表 1. 基于彩虹的二次开发 - 对彩虹系统进行了二次开发&#xff0c;增强了系统的功能和性能。2. 新增自定义输入框提示内容&#xff08;支持批量修改&#xff09; - 用户可以自定义输入框的提示内容&#xff0c;并支持批量修改&#xff0c;提升用户体验。3. 新…

TCP相关特性

协议段格式 • 源/⽬的端⼝号:表⽰数据是从哪个进程来,到哪个进程去; • 32位序号/32位确认号:后⾯详细讲; • 4位TCP报头⻓度:表⽰该TCP头部有多少个32位bit(有多少个4字节);所以TCP头部最⼤⻓度是15*460 • 6位标志位: ◦ URG:紧急指针是否有效 ◦ ACK:确认号是否有效…

c++高精度减法的方法和示例代码

C中的高精度减法指的是在处理大数时&#xff0c;执行减法操作的方法。通常情况下&#xff0c;C内置的数据类型&#xff08;如int、long、double等&#xff09;可能无法满足大数运算的需求&#xff0c;因为它们的范围有限。在这种情况下&#xff0c;需要使用自定义的数据结构或者…

深入理解逻辑运算符:从基础到实战技巧

在 JavaScript 编程中&#xff0c;逻辑运算符是处理条件和控制流程的重要工具。 本文将从基础知识出发&#xff0c;向初学者介绍逻辑运算符的基本用法&#xff0c;并深入探讨工作中常用的一些技巧。 1. 基础知识 逻辑与操作符 && 在两个条件都为真时返回真。 if (…

ARMv8架构特殊寄存器介绍-0

一、zero 寄存器 零寄存器用作源寄存器时读取零&#xff0c;用作目标寄存器时丢弃结果。您可以在大多数指令中使用零寄存器&#xff0c;但不是所有指令。二、sp寄存器 在ARMv8架构中&#xff0c;要使用的堆栈指针的选择在某种程度上与Exception级别。默认情况下&#xff0c;异…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:ScrollBar)

滚动条组件ScrollBar&#xff0c;用于配合可滚动组件使用&#xff0c;如List、Grid、Scroll。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 可以包含单个子组件。 接口 ScrollBar(val…

Linux系统——rsync命令

目录 一、rsync介绍 1.rsync简介 2.rsync同步基本说明 二、rsync用法 1.rsync三种工作方式 2.rsync选项详解 不带任何选项 -t -I&#xff08;i&#xff09; -v -z -r -l&#xff08;L&#xff09; -p——perserve permissions&#xff08;保持权限&#xff09; …