资源管理系统(Asset Management System)
A-Frame允许我们把资源集中放在一个地方,便于预加载和缓存来达到更好的性能。
游戏和富客户端3D体验传统上会在渲染场景之前预加载资产,如模型或纹理贴图,这样可以确保资源不会出现视觉丢失,避免场景试图在渲染时才去获取资产所导致的性能问题。
我们把资源放在<a-assets>
里面,并且我们把<a-assets>
放在<a-scene>
中。资源包括:
<a-asset-item>
- 杂项资产,如三维模型和材料<audio>
- 音频文件<img>
- 图像纹理<video>
- 视频纹理
在浏览器获取(或发生错误退出)所有资源或资源超时之前,场景不会呈现或初始化。
示例
我们可以在<a-assets>
中定义资源,然后在实体中我们可以使用查询器来引用这些资源:
<a-scene> <!-- Asset management system. --> <a-assets> <a-asset-item src="horse.obj"></a-asset-item> <a-asset-item src="horse.mtl"></a-asset-item> <a-mixin scale="5 5 5"></a-mixin> <audio src="neigh.mp3"></audio> <img src="ad.png"> <video src="derby.mp4"></video> </a-assets> <!-- Scene. --> <a-plane src="advertisement"></a-plane> <a-sound src="#neigh"></a-sound> <a-entity geometry="primitive: plane" material="src: #kentucky-derby"></a-entity> <a-entity mixin="giant" obj-model="obj: #horse-obj; mtl: #horse-mtl"></a-entity></a-scene> |
场景及其实体在初始化和呈现之前将等待所有资源加载完毕(或者超时)。
跨域资源共享(CORS)
由于A-Frame使用XHRs来获取资源,如果资源放在不同域中,浏览器安全性要求资源通过跨域资源共享消息头来提供。否则,我们必须把资源托管在和场景应用相同域名上。
作为一个可选项,GitHub Pages支持跨域资源共享消息头,我们把它作为一个简单的发布平台。
如果设置了<a href="https://www.xnip.cn/wp-content/uploads/2021/docimg15/91-xug4dwxwlgy.png"> </a-asset></a-scene>
事件(Events)
由于<a-assets>
和<a-asset-item>
是A-Frame里的节点(nodes),它们加载完成时将发出loaded
事件:
事件名称 | 描述 |
---|---|
loaded | 所有资源都已经加载完成,或者已超时。 |
timeout | 资源加载超时。 |
单个资源的加载进度
<a-asset-item>
<a-asset-item>
调用three.js FileLoader。我们可以把<a-asset-item>
用于任何文件类型。当结束时,它将设置其data
成员为响应文本。
事件名称 | 描述 |
---|---|
error | 获取错误。事件详情里面包含了一个带XMLHttpRequest 实例的xhr 。 |
progress | 进度上报。事件详情里面包含了一个带XMLHttpRequest 实例的xhr ,loadedBytes 和totalBytes 。 |
loaded | 通过src 指向的资源已经加载完成。 |
<img>
图像是标准的DOM元素,因此我们可以侦听标准的DOM事件。
事件名称 | 描述 |
---|---|
load | 图像已加载。 |
HTML媒体元素(HTMLMediaElement)
音频和视频资源是HTMLMediaElement
。对应的浏览器触发事件有些特别,列举如下:
事件名称 | 描述 |
---|---|
error | 资源加载时发生错误。 |
loadeddata | 已加载数据。 |
progress | 进度。 |
A-Frame使用这些进度事件,和浏览器资源缓存时长相比较,来检测何时资源加载完成。
指定响应类型
通过<a-asset-item>
获取的内容将以普通文本形式返回。如果我们需要不同的形式比如arraybuffer
,可以使用<a-asset-item>
的response-type
属性来指定:
<a-asset-item response-type="arraybuffer" src="model.gltf"></a-asset-item> |
运行原理
A-Frame中所有元素都从<a-node>
继承而来,AFRAME.ANode
原型。ANode
控制加载和初始化顺序。要初始化一个元素(无论它是<a-assets>
, <a-asset-item>
, <a-scene>
,还是<a-entity>
),其子元素必须已经初始化。节点是自下而上初始化的。
<a-assets>
是一个ANode
,它将等待其子节点加载完成后才加载自身。并且由于<a-assets>
是<a-scene>
的子元素,场景事实上将需要等待所有资源加载完成。我们还添加额外的加载逻辑到 <a-entity>
上,比如它们显式的等待<a-assets>
加载,如果我们定义了<a-assets>
。
<a-asset-item>
使用THREE.FileLoader
来获取文件。three.js存储返回数据在THREE.Cache
中。每个three.js加载器从THREE.FileLoader
继承而来,无论它们是一个ColladaLoader
,OBJLoader
, 还是ImageLoader
等。它们都能访问中央缓存THREE.Cache
。如果A-Frame已经获取了一个文件,那么将无需再次获取,我们可以直接使用缓存中的数据。
这样,由于我们在加载资源时阻塞了实体的初始化,到实体加载完成时,所有的资源必然是已经被加载完成了。只要我们定义<a-asset-item>
,并且实体使用THREE.FileLoader
来加载资源,那么缓存机制将自动工作。
访问文件加载器(FileLoader)
和缓存(Cache)
我们也可以直接访问three.js的FileLoader
:
console.log(document.querySelector('a-assets').fileLoader); |
To access the cache that stores XHR responses:
console.log(THREE.Cache); |