在 javascript 中使用 A 帧 img 资产
Use A-frame img assets inside javascript
我多次使用图像作为纹理,一次是通过 material 组件,另一次是在自定义组件中。在后者中,我使用 THREE.TextureLoader()
导致应用程序 加载图像两次 。我敢打赌还有另一种方式。
现状
HTML
<!-- Assets -->
<a-assets>
<img id="my-map" src="path/to/map.jpg">
<a-asset-item id="my-model" src=path/to/model.gltf""></a-asset-item>
</a-assets>
<!-- Entities -->
<a-box material="src: #my-map">
<a-entity gltf-model="src: #my-model" custom-component="mymap: #my-map">
JS
// custom-component extract
schema: { mymap: { type: 'map' } }
init: function()
{
let mesh = this.el.getObject3D('mesh')
mesh.traverse( function( child )
{
if ( child.isMesh )
{
let TextureLoader = new THREE.TextureLoader()
let mymap = TextureLoader.load( data.mymap )
child.material = new THREE.MeshPhongMaterial({ map: mymap })
child.material.needsUpdate = true;
}
})
}
问题
如何在自定义组件中使用相同的图像资源而不加载它两次?
您正在使用 mesh.traverse()
,它会在 mesh
的每个 child 中调用您的函数一次。如果您的网格中有两个 children,它会调用 TextureLoader.load()
两次。只需从 traverse()
中取出加载调用,您应该会看到图像只加载了一次。
let mesh = this.el.getObject3D('mesh')
let TextureLoader = new THREE.TextureLoader()
let mymap = TextureLoader.load( data.mymap )
mesh.traverse( function( child )
{
if ( child.isMesh )
{
child.material = new THREE.MeshPhongMaterial({ map: mymap })
child.material.needsUpdate = true;
}
})
在深入研究 ThreeJs 代码后,我发现 TextureLoader
依赖于 ImageLoader
(参见 here) which, before loading a new image, it looks into THREE.Cache
to see if the image has already been loaded (see here)。
在 AFrame 中以 img
加载图像不会将它们存储在 THREE.Cache
中,因此图像被加载了两次。但是,如果您将图像加载为 a-asset-item
,它会加载图像。
因此 javascript 中无需更改任何内容。只需使用 a-asset-item
而不是 img
。
有关详细信息,请参阅 AFrame documentation
我多次使用图像作为纹理,一次是通过 material 组件,另一次是在自定义组件中。在后者中,我使用 THREE.TextureLoader()
导致应用程序 加载图像两次 。我敢打赌还有另一种方式。
现状
HTML
<!-- Assets -->
<a-assets>
<img id="my-map" src="path/to/map.jpg">
<a-asset-item id="my-model" src=path/to/model.gltf""></a-asset-item>
</a-assets>
<!-- Entities -->
<a-box material="src: #my-map">
<a-entity gltf-model="src: #my-model" custom-component="mymap: #my-map">
JS
// custom-component extract
schema: { mymap: { type: 'map' } }
init: function()
{
let mesh = this.el.getObject3D('mesh')
mesh.traverse( function( child )
{
if ( child.isMesh )
{
let TextureLoader = new THREE.TextureLoader()
let mymap = TextureLoader.load( data.mymap )
child.material = new THREE.MeshPhongMaterial({ map: mymap })
child.material.needsUpdate = true;
}
})
}
问题
如何在自定义组件中使用相同的图像资源而不加载它两次?
您正在使用 mesh.traverse()
,它会在 mesh
的每个 child 中调用您的函数一次。如果您的网格中有两个 children,它会调用 TextureLoader.load()
两次。只需从 traverse()
中取出加载调用,您应该会看到图像只加载了一次。
let mesh = this.el.getObject3D('mesh')
let TextureLoader = new THREE.TextureLoader()
let mymap = TextureLoader.load( data.mymap )
mesh.traverse( function( child )
{
if ( child.isMesh )
{
child.material = new THREE.MeshPhongMaterial({ map: mymap })
child.material.needsUpdate = true;
}
})
在深入研究 ThreeJs 代码后,我发现 TextureLoader
依赖于 ImageLoader
(参见 here) which, before loading a new image, it looks into THREE.Cache
to see if the image has already been loaded (see here)。
在 AFrame 中以 img
加载图像不会将它们存储在 THREE.Cache
中,因此图像被加载了两次。但是,如果您将图像加载为 a-asset-item
,它会加载图像。
因此 javascript 中无需更改任何内容。只需使用 a-asset-item
而不是 img
。
有关详细信息,请参阅 AFrame documentation