【发布时间】:2020-01-09 01:18:09
【问题描述】:
我正在制作一个在解析 json 文件后从代码生成实体的场景。 一切正常,除了纹理加载。
为了简化问题,我在这个故障中重建了最低要求 https://glitch.com/~generate-scene
<script>
AFRAME.registerComponent("make-spheres", {
init: function(){
var sceneEl = document.querySelector('a-scene');
var entityEl = document.createElement('a-entity');
entityEl.setAttribute('id', 'sphere1');
entityEl.setAttribute('geometry', { primitive: 'sphere', radius: 0.5});
entityEl.setAttribute('material', { color: 'white', src: 'assets/pano_1.png', opacity: 0.5});
entityEl.setAttribute('position', "0 0.25 0");
entityEl.setAttribute('animation__opacity',{ property: "components.material.material.opacity", from: 0.1, to: 1, dur: 1500, loop: true, dir:"alternate"});
entityEl.setAttribute('animation__pos1',{ property: 'position', to: "0 2 0", from: "0 0.85 0", dur: 1500, easing: "linear", loop: true, dir:"alternate"});
entityEl.setAttribute('do-something-once-loaded', '');
sceneEl.appendChild(entityEl);
}
});
</script>
<body>
<a-scene>
<a-entity id="setup" make-spheres></a-entity>
在这里,纹理加载并且一切正常。
但在我较大的项目中,动态加载组件代码隐藏在 fetch promise 中,纹理无法加载并引发错误和警告。
HTTP 加载失败,状态为 404。媒体资源 http://localhost:3000/assets/pano_1.png 加载失败。 panomaker.html
components:texture:warn $s 不是有效的视频资产/pano_1.png
AFRAME.registerComponent("init-spheres", {
init: function(){
let el = this.el;
let self = this;
self.parent = el; // Ref to 3D entity that will be the parent of all newly created entities (spheres, buttons, etc).
// load the json file used to populate the scene
fetch("../data.json")
.then(function(response){
return response.json(); // convert data to json object
})
.then(function(body) {
// When data has been converted, start generating 3D
//console.log('fetch data response: ', body);
let panosArray = body.data;
// Create the pano objects from the json data
self.panos = getPanoramas(panosArray);
...
// creating sphere panos
self.panos.forEach(function(pano){
// Create the pano spheres.
pano['sphere'] = document.createElement("a-entity");
pano.sphere.setAttribute('id', "panoSphere_"+pano.id);
pano.sphere.setAttribute('geometry', {primitive: 'sphere', radius: pano.avgDistance});
pano.sphere.setAttribute('position', pano.position.x.toString()+' '+pano.position.y.toString()+' '+pano.position.z.toString() );
pano.sphere.setAttribute('scale', "-1 1 1");
pano.sphere.setAttribute('visible', true);
// set the src to the pano texture. src: pano.texture, opacity: 1, shader: "flat", side:"back", npot: true, blending: "normal",
let texName = "assets/"+pano.texture;
pano.sphere.setAttribute('material', {color: "#ffffff", src: 'assets/pano_1.png', transparent: true } ); //src: texName,
self.sceneEl.appendChild(pano.sphere);
});
为什么在较大的项目中加载失败,但在较小的项目中却可以正常工作?
问题似乎是纹理尚未准备好加载,或者可能有什么东西阻止了加载。我很困惑。
我注意到有两种方法可以在 AFrame 中加载纹理。
1)在材质中使用直接路径:src属性
material="src: texture.png"
2) 将资产创建为 img 元素,并在 material: src 属性中引用其 id 标签。
<a-assets>
<img id="my-texture" src="texture.png">
</a-assets>
material="src: #my-texture"
两种方法都可以,但首选第二种方法,因为它会预加载纹理,防止错误。 我上面的代码使用的是方法 1,它在简单版本中有效,在更复杂的项目中失败。所以我假设,如果我可以在代码中创建一个资产 img 源,那么这可能会起作用。但我还没有找到让它工作的方法。 我正在尝试这个
// Create the image assets for the scene
let assets = document.querySelector('a-assets');
// Create the pano textures.
let name = 'panotex_'+pano.id;
let texture = document.createElement('img');
texture.setAttribute('id', name);
texture.onload = function(){
console.log('texture loaded');
}
texture.onerror = function(){
console.log('texture failed');
}
let texPath = "assets/"+pano.texture;
texture.setAttribute('src', texPath);
assets.appendChild(texture);
但这会导致纹理无法加载并在控制台中抛出“纹理失败”。
预加载纹理、将其附加到 a-assets 并执行加载纹理时将运行的处理函数的最佳方法是什么?
【问题讨论】:
标签: aframe