Cocos使用精灵组件显示相机内容

news/2024/12/14 12:08:38/

Cocos使用精灵组件显示相机内容

1. 为什么使用精灵渲染

在游戏引擎中,游戏场景内除webviewvideo外所有的节点都是渲染在Canvas上,这导致了webviewvideo只能存在于所有节点的最上层或最下层,而这种层级关系会出现节点事件无法正常监听或者webviewvideo被遮挡,为解决这个问题可以通过将影像渲染在精灵组件上。

2. 如何实现

2.1 添加视频标签

可以直接用代码创建,也可以在构建后添加到index.html文件中;

// 创建一个新的视频元素
let video = document.createElement("video");
// 设置视频元素的 ID
video.setAttribute('id', 'local_video');
// 设置视频预加载属性为自动
video.setAttribute('preload', 'auto');
// 将视频元素隐藏
video.setAttribute('hidden', 'hidden');
// 设置视频元素的样式,宽高都为0,以隐藏视频
video.setAttribute('style', 'width: 0px; height: 0px;')
// 将视频元素添加到文档的主体中
document.body.appendChild(video);

2.2 逻辑实现

原理是将视频内容根据自己设置的固定帧绘制在画布,再将纹理转换成精灵帧显示在精灵组件上;(适用于相机采集、直播采集、视频文件播放等)

private _texture: cc.Texture2D; // 用于存储纹理
private _canvas: HTMLCanvasElement; // HTML画布元素
private _canvasCtx: CanvasRenderingContext2D; // 画布的2D上下文
private _sprite: cc.Sprite; // 精灵组件private spriteFrameCache: cc.SpriteFrame[] = []; // 精灵帧缓存数组
private index = 0; // 当前使用的缓存索引
private _video; // 视频元素private lastUpdateTime = -1; // 上一次更新时间
private _Timer = 0; // 定时器init() {// 创建画布并设置尺寸let canvas: HTMLCanvasElement = document.createElement('canvas');canvas.width = this.node.width; // 设置画布宽度canvas.height = this.node.height; // 设置画布高度this._canvas = canvas; // 保存画布引用this._canvasCtx = canvas.getContext('2d'); // 获取2D上下文this._sprite = this.getComponent(cc.Sprite); // 获取精灵组件this._texture = new cc.Texture2D(); // 创建新的纹理对象// 初始化两个精灵帧并存入缓存for (let i = 0; i < 2; i++) {this.spriteFrameCache.push(new cc.SpriteFrame()); // 创建精灵帧并加入缓存}
}
private async updateTexture(): Promise<void> {// 如果视频未定义,返回if (this._video == undefined) return;// 如果视频未暂停且当前时间与最后更新时间不同,进行更新if (!this._video.paused && this._video.currentTime !== this.lastUpdateTime) {this.lastUpdateTime = this._video.currentTime; // 更新最后更新时间this._Timer = 0; // 重置计时器} else if (this._Timer < 10) {this._Timer += 1 / 25; // 增加计时器} else {this.unschedule(this.updateTexture); // 取消调度this.clearSprite(); // 清空精灵this._Timer = 0; // 重置计时器console.log('updateTexture fail'); // 打印失败日志return; // 返回}// 在画布上绘制视频内容this._canvasCtx.drawImage(this._video, 0, 0, this.node.width, this.node.height);this._texture.initWithElement(this._canvas); // 用画布元素初始化纹理let spriteFrame = this.spriteFrameCache[this.index]; // 获取当前索引的精灵帧spriteFrame.setTexture(this._texture); // 设置精灵帧的纹理this._sprite.spriteFrame = spriteFrame; // 更新精灵的显示帧this.index = this.index ^ 1; // 切换索引(0 和 1 之间切换)
}
bind(cb): void {// 获取本地视频元素this._video = document.querySelector("#local_video").children[0];// 请求用户媒体(音频和视频)navigator.mediaDevices.getUserMedia({audio: true,video: true}).then((stream) => {this.handleSuccess(stream); // 成功时处理流this._video.play(); // 播放视频cb(); // 调用回调}).catch(this.handleError); // 处理错误
}
handleSuccess(stream) {this._video.srcObject = stream; // 将流设置为视频播放器的源对象
}
handleError(e) {console.log("绑定失败:"); // 输出错误信息console.log(e); // 输出具体错误
}
clearSprite() {this._sprite.spriteFrame = null; // 清空精灵的显示帧
}
/**调用测试 **/
test() {this.bind(() => { // 绑定视频流并在完成后执行回调this.unschedule(this.updateTexture); // 取消之前的调度this.schedule(this.updateTexture, 1 / 25, cc.macro.REPEAT_FOREVER); // 调度更新纹理的方法this.init(); // 初始化设置});
}

http://www.ppmy.cn/news/1544344.html

相关文章

【1】Excel快速入门的核心概念

1. 工作表 基本工作表 图表工作表 工作表视图 2.表格(Table)&#xff0c;套用表格格式 ​ 名称&#xff08;表&#xff0c;列&#xff09; ​ 结构化引用[列名] ​ 设置表格样式 -可自定义&#xff08;如报表类&#xff09; ​ 数据验证 -交互 &#xff08;输入/输出交…

MATLAB/Simulink学习|在Simulink中调用C语言-04使用C Function 实现PI运算(使用模块自定义代码-仿真自定义代码)

在上一篇博客中&#xff0c;介绍了如何使用C Function 实现PI运算&#xff0c;但是在模块内编辑C代码&#xff0c;而不能直接调用已经写好了的C代码。 在Simulink中使用C Function调用自定义代码有两种方法&#xff0c;本篇博客介绍其中一种方法。 添加头文件和源文件 在实际…

P10424 [蓝桥杯 2024 省 B] 好数 题解

题目名字 P10424 [蓝桥杯 2024 省 B] 好数 题解 题目链接 题意 给一个整数n&#xff0c;从1到n这个区间范围内&#xff0c;每一个数位为偶数的数字为偶数且数位为奇数的数字为奇数&#xff0c;那么这个数就是好数 思路 首先确认所有的条件都必须要满足&#xff0c;奇对奇&…

ubuntu20安装opencv3.2记录

系统环境 ubuntu20安装了ros-noetic&#xff0c;所以系统默认装了opencv4.2.0&#xff0c;但是跑fastlivo推荐的是opencv3.2.0&#xff0c;而且海康相机别人写的ros驱动&#xff08;海康相机ros驱动&#xff09;也是需要opencv3.2.0&#xff0c;最终还是选择安装多版本的openc…

第三十章 章节练习商品列表组件封装

目录 一、需求说明 二、技术要点 三、完整代码 3.1. main.js 3.2. App.vue 3.3. MyTable.vue 3.4. MyTag.vue 一、需求说明 1. my-tag 标签组件封装 (1) 双击显示输入框&#xff0c;输入框获取焦点 (2) 失去焦点&#xff0c;隐藏输入框 (3) 回显标签信息 (4) 内…

LeetCode 2487.从链表中移除节点

题目&#xff1a; 给你一个链表的头节点 head 。 移除每个右侧&#xff08;右侧所有&#xff09;有一个更大数值的节点。 返回修改后链表的头节点 head 。 思路&#xff1a; 代码&#xff1a; class Solution {public ListNode removeNodes(ListNode head) {head revers…

Unity Job System详解(3)——NativeList源码分析

【前言】 查看NativeList源码需要安装Unity的Entities Package NativeList要实现的基本功能类似C# List&#xff0c;如下&#xff1a; &#xff08;一些简单的类同NativeArray的不在说明&#xff09; 构造函数、析构函数、取值赋值 扩容、添加、移除操作 解析步骤包括&am…

vite5 打包项目兼容ie和低版本chrome

背景&#xff1a; vite打包后的项目 在低版本chrome无法使用 直接打包项目在69版本的chrome上无法加载 报错 解决方法&#xff1a; 使用vite官方推荐的插件 vitejs/plugin-legacy 1、下载 npm i vitejs/plugin-legacy -D 2、vite.config.js import legacy from "vit…