uniApp开发XR-Frame微信小程序 | 动态加载与删除模型

在使用xr-frame开发3D小程序时,我们经常需要根据需求去动态加载模型或删除模型,在官方的说明中,提到了相关方法,但并不太明确,也没有确切的实例。

我们先来看一下官方给出的说明。

一. Shadow元素

我们需要用代码动态创建元素之后添加到场景中,这个需求和wxml写标签这种静态的模板编译方式是冲突的,为了保证DOM树不混乱,我们提供了类似于HTML中的ShadowRoot的XRShadow元素,对应于xml中的xr-shadow标签,来解决这个问题。

<xr-shadow id="shadow" position="0 1 0" />

也就是说,我们要动态添加模型,就需要在这个xr-shadow元素下操作。

我们先来看一下实例

实例中,我们通过点击下一个按钮,将xr-frame框架中的模型卸载后再重新加载一个新的模型。

二.代码实现

下面我们从源码角度来讲解如何实现。

(1)index.wxml 中的部分代码

<xr-scene render-system="alpha:true" bind:ready="handleReady"><xr-light type="ambient" color="1 1 1" intensity="1" /><xr-light type="directional" rotation="40 150 0" color="1 1 1" intensity="3" cast-shadow /><xr-node node-id="target" anim-keyframe="anim" anim-autoplay="clip:cube"><xr-shadow id="shadow" position="0 0 0" /></xr-node><xr-env env-data="xr-frame-team-workspace-day" sky-map="weakme"/><xr-camera id="camera" clear-color="0 0 0 0" position="0 0.5 1.5" target="target" camera-orbit-control background="skybox"/>
</xr-scene>

上面的代码中,我们主要看

<xr-shadow id="shadow" position="0 0 0" />

这段源码就是shadow元素,我们要添加和删除模型,都是在这个元素里操作的。

我们给shadow元素设置了id,就是用于在 index.js 文件中查找这个元素,然后通过xr-frame框架下的API操作在这个元素下添加新的节点。

(2)获取场景中的shadow节点

 index.js 中的源码中

handleReady({detail}) {this.xrFrameSystem = wx.getXrFrameSystem()this.scene = detail.valuethis.control.isLockZoom = truethis.shadow = this.scene.getElementById('shadow')// 给父组件发送通知this.triggerEvent('sceneReady',"ready")},

handleReady() 这个函数表示场景加载完成后执行的回调函数。

在这个函数中,我们通过 this.scene = detail.value 获取到了场景的根节点信息,这一步是基础,获取到场景的根节点后,才能获取更多的子节点。

随后,我们通过 this.shadow =this.scene.getElementById('shadow') 获取到了 shadow 元素的节点,下一步,我们就要实现在 shadow 元素下添加子节点的操作了。

(3)使用api动态创建gltf节点到shadow中。

async addGltf() {//1 创建xr-gltf元素const el = this.scene.createElement(this.xrFrameSystem.XRGLTF)//2 获取shadow节点this.shadow = this.scene.getElementById('shadow')//3 将xr-gltf节点加入到shaodow节点中this.shadow.addChild(el)//4 读取对应的模型文件const { value: model} = await this.scene.assets.loadAsset({type: 'gltf',assetId: 'gltfmodel',src: modelsrc})// 5 获取gltf组件this.gltfComp = el.getComponent('gltf') // 6 给gltf组件设置模型数据this.gltfComp.setData({model: model})// 7 给元素设置一个ID,用于后续方便removeel.setId(name)
}

注意:这个函数前面加了 async ,是一个异步函数。

因为在函数中我们需要做加载模型文件的操作,这个操作可能会很耗时,需要视网络情况和模型大小而定。

下面我们一步步解析:

..1 源码中,我们先创建了一个xr-gltf元素

const el = this.scene.createElement(this.xrFrameSystem.XRGLTF)
        这里通过框架的API createElement()我们创建了一个元素

..2 然后将该元素作为子元素添加到shadow元素中

//2 获取shadow节点
this.shadow = this.scene.getElementById('shadow')
//3 将xr-gltf节点加入到shaodow节点中
this.shadow.addChild(el)
        这里我们先通过 getElementById() 方法找到shadow节点。
        然后,通过 addChild() 方法将创建的XRGLTF元素添加到节点下。

..3 通过 scene.assets.loadAsset() 方法加载一个模型资源

const { value: model} = await this.scene.assets.loadAsset({type: 'gltf',assetId: 'gltfmodel',src: modelsrc})
这个方法中有几个属性:
type 表示要加载的资源类型,这里设置为gltf。
assetId 表示设置的资源ID,这个可以用于后期清理资源。
src 表示资源的网络地址。
这里需要注意的一点,scene.assets.loadAsset() 这个方法要加载资源,有时耗费时间会比较长,所以这里采用async/await 的语法来进行异步操作。

..4 获取到xr-gltf元素中的 gltf 组件

this.gltfComp = el.getComponent('gltf') 
这一部,我们获取到了元素XRGLTF元素中的gltf组件

..5 给组件设置属性

// 6 给gltf组件设置模型数据
this.gltfComp.setData({model: model})
// 7 给元素设置一个ID,用于后续方便remove
el.setId(name)
这一步我们给组件中的model属性设置了变量名为 model 的对象
这个 model 就是我们第3步加载的模型对象
最后我们给元素 el 设置了一个id。用于后期清理资源使用。

(4)清理资源

在官方说明中,通过动态加载的资源需要自己手动释放,不然如果加载越来越多,会对程序造成卡顿。

release(name) {//1 删除节点this.shadow.removeChild(this.scene.getElementById(name))//2 释放资源this.scene.assets.releaseAsset('gltf', name)
},

上面代码中,我们首先调用了 shadow.removeChild() 方法,移除了shadow下的子节点。

然后通过 scene.assets.releaseAsset()方法,释放了加载的gltf资源。

函数中的参数 name 就是我们给上一步创建的 el 设置的 id

函数中的这两个方法都是xr-frame官方api中的方法,详细的解释可以看一下官方文件。

关于释放资源的时机,可以根据自己的场景需求进行合理的设计。

三.附件说明

附件中的代码就是本篇文章用到的动态加载模型的xr-frame组件中的代码。

代码中我做了一些优化,由于gltf文件有时会过大,所以我采用模型和贴图分开加载的方法,加载完成后再给模型设置上贴图。

大家可以参考学习,如果不会配置需要查看一下这篇文章,xr-frame基础环境搭建。

四.示例小程序

附件中的小程序码,是我根据官方指南做的一个简易的示例程序,其中运用了场景的搭建,材质动态修改,模型动态添加与删除,粒子特效等功能,可以作为本片文章的参考。

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

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

相关文章

把多个 PPT 合并在一起,三步告别复制粘贴

制作部门汇报分册、项目阶段文件等工作需要将多个零散的PPT合并为一份完整文档。手动复制粘贴不仅效率低下&#xff0c;还容易导致格式错乱、动画丢失。本文介绍一种高效方法&#xff0c;三步操作即可将多个PPT文件快速合并为单一文档。无论是整合汇报材料&#xff0c;还是准备…

安卓旋转屏幕后如何防止数据丢失-ViewModel入门

Android ViewModel 入门教程 在日常开发中&#xff0c;当 Activity 因为旋转屏幕或内存回收被销毁重建时&#xff0c;UI 中的数据也会丢失。 这时候&#xff0c;Android Jetpack 提供的 ViewModel 就能帮我们解决这个问题。 1. 什么是 ViewModel ViewModel 是一种架构组件。它专…

Linux 下的 Vim 使用与网络安全配置详解

目录 引言 一、Vim 编辑器的使用 1. Vim 的模式 2. 常用操作命令 3. 保存与退出 4. 多窗口与 Shell 切换 二、Linux 网络基础 1. 网络分类 2. IP 地址与分类 三、网络配置与工具 1. ifconfig 2. netstat 3. wget 4. 主机名与 IP 映射 四、Linux 防火墙与安全设置…

Docker 容器传输文件的常用方法

Docker 容器传输文件的常用方法 在 Docker 日常使用中&#xff0c;经常需要在主机与容器之间传输文件&#xff08;如配置文件、代码包、日志等&#xff09;。以下是四种最常用的实现方式&#xff0c;覆盖临时传输、持久共享、构建集成等不同场景。 1. 使用 docker cp 命令&…

视频转音频在线工具大比拼,哪家体验更胜一筹?

最近工作上遇到了个挺有意思的需求&#xff0c;需要从几个教学视频里提取出音频内容&#xff0c;方便做成播客形式&#xff0c;让学员能随时随地学习。一开始&#xff0c;我以为这活儿挺简单的&#xff0c;不就是把视频里的声音单独弄出来嘛&#xff0c;结果一上手才发现&#…

KafKa02:Kafka配置文件server.properties介绍

一、配置文件位置二、配置文件介绍默认下&#xff1a;9092 是处理消息队列核心业务&#xff08;客户端与 broker 交互&#xff09;的端口9093 是集群内部控制器通信的端口# 指定节点角色&#xff0c;这里同时作为 broker&#xff08;消息代理&#xff09;和 controller&#xf…

哈尔滨云前沿服务器租用托管

黑龙江前沿数据&#xff0c;始建于2005年&#xff0c;多年的历史&#xff0c;专业从事域名注册&#xff0c;虚拟主机&#xff0c;服务器租用&#xff0c;云主机&#xff0c;网站建设等互联网服务。电信/联通/双线/机房/众多机房供您选择&#xff0c;总有一个适合您的服务器&…

Qt开发经验 --- Qt 修改控件样式的方式(16)

文章目录[toc]1 概述2 Qt Style Sheets (QSS)3 使用 QStyle 和 QProxyStyle4 设置 Palette (调色板)5 使用预定义的 QStyle6 直接设置控件属性7 自定义控件绘制更多精彩内容&#x1f449;内容导航 &#x1f448;&#x1f449;Qt开发经验 &#x1f448;1 概述 Qt 提供了多种修改…

Vue3》》Svg图标 封装和使用

SVG 安装插件 npm i vite-plugin-svg-icons // vite.config.ts import { defineConfig } from vite import vue from vitejs/plugin-vue import { createSvgIconsPlugin } from vite-plugin-svg-icons import { resolve } from path export default defineConfig({//配置路径别…

【04】AI辅助编程完整的安卓二次商业实战-寻找修改替换新UI首页图标-菜单图标-消息列表图标-优雅草伊凡

【04】AI辅助编程完整的安卓二次商业实战-寻找修改替换新UI首页图标-菜单图标-消息列表图标-优雅草伊凡引言本次二开布局没有变&#xff0c;但是下一次整体布局会有变&#xff0c;不过本次开发发现朋友圈跳转功能的流程步骤也做了一定的变化。原生项目复杂就复杂于就算一个颜色…

龙蜥8.10中spark各种集群及单机模式的搭建spark3.5.6(基于hadoop3.3.6集群)

先说最终的访问端口&#xff0c;如我这里ip为172.20.94.37、172.20.94.38、172.20.94.39&#xff0c;主机名分别为&#xff1a;hadoop37、hadoop38、hadoop39. 最终访问&#xff08;默认端口&#xff09;&#xff1a; hadoop webui 172.20.94.37:9870 hdfs 端口 8020 yarn 172.…

关于我重新学习 react 的第一遍

今天是25年9月11号&#xff0c;很久很久没有学习前端知识了&#xff0c;坦诚来说还清楚记得在大学里因为前端技术第一次获奖的心情&#xff0c;也清晰记得写完第一篇博客后的心情&#xff0c;工作和运动给我最大程度的成就感。 打破自己 重新开始 完全地 版本一 25.9.11 文章目…

第2课:Agent系统架构与设计模式

第2课&#xff1a;Agent系统架构与设计模式 课程目标 理解Agent的基本概念和特性掌握多Agent系统的设计模式学习Agent通信协议和消息传递实践创建简单的Agent框架 课程内容 2.1 Agent基础概念 什么是Agent&#xff1f; Agent是一个具有自主性、反应性、社会性和主动性的计…

Day42 51单片机中断系统与8×8 LED点阵扫描显示

day42 51单片机中断系统与88 LED点阵扫描显示一、51单片机引脚位操作 —— sbit 关键字 作用 sbit 是专用于 51 单片机架构的 C 语言扩展关键字&#xff0c;用于定义特殊功能寄存器&#xff08;SFR&#xff09;中的某一位&#xff0c;从而实现对单个 I/O 引脚的直接位操作。 示…

差分: 模板+题目

题目&#xff1a;【模板】差分 应用场景&#xff1a;快速解决将某一个区间所有元素加上 “一个数” 的操作。 第一步&#xff0c;预处理差分数组。 f[i] 表示&#xff1a;当前元素与前一个元素的差值 a[i] - a[i-1]; 但在题目中&#xff0c;我们其实可以不用到a[]这个数组…

GD32 Timer+ADC多通道+DMA+PWM调试记录

本例记录使用GD32307C开发板&#xff0c;实现以内部Timer1 CH1为触发源&#xff0c;触发ADC0的两个通道&#xff0c;进行并行非连续采样&#xff0c;病通过DMA传输采样结果。同时输出PWM&#xff0c;用来检测Timer1 CH1的触发周期。下面介绍具体实现过程&#xff1a;1. gpio初始…

阻塞 IO为什么叫BIO,非阻塞IO为什么叫NIO,异步IO为什么叫AIO

IOIO的核心就是数据传输&#xff0c;也就是程序与外部设备之间进行传输&#xff0c;通过IO的核心可以分为&#xff0c;文件IO和网络IO文件IO交互的对象就是本地存储设备&#xff0c;比方说读写本地文件。网络IO交互的对象就是网络设备&#xff0c;核心的应用场景就是网络通信。…

10分钟了解什么是多模态大模型

10分钟了解什么是多模态大模型&#xff08;MM-LLMs&#xff09; 1. 什么是多模态 Multimodality 多模态&#xff08;Multimodality&#xff09;是指集成和处理两种或两种以上不同类型的信息或数据的方法和技术。在机器学习和人工智能领域&#xff0c;多模态涉及的数据类型通常…

通过DSL生成Jenkins流水线

代码化管理 Jenkins 流水线&#xff08;Infrastructure as Code&#xff09; 版本控制&#xff1a;DSL 脚本可以像代码一样存入 Git、GitLab 等版本控制系统&#xff0c;所有任务配置的变更都有提交记录&#xff0c;便于追溯历史、回滚错误。协作效率&#xff1a;团队成员可以通…

信号量主要API及综合应用

1.信号量概述信号量是一个底层核心模块【int】类型变量&#xff0c;记录当前信号量数据。信号量 P 操作 (sem_wait)线程检测对应信号量底层 int 数据数值&#xff0c;如果大于 0&#xff0c;当前线程获得 CPU 执行权&#xff0c;同时将信号量底层 int 数据-1 操作。如果底层数据…