我正在制作一个场景,该场景在解析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>
在这里,纹理加载并且一切正常。
但是在我的更大项目中,动态加载组件代码被隐藏在获取承诺中,纹理无法加载,并引发错误和警告。
HTTP加载失败,状态为404。媒体资源http://localhost:3000/assets/pano_1.png的加载失败。 panomaker.html
组件:纹理:警告$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元素,并在材料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 并执行将在加载纹理时运行的处理函数的最佳方法是什么?
答案 0 :(得分:0)
loading textures with THREE.js怎么样?
如果您有图像路径,则可以将其提供给THREE.TextureLoader
对象:
// assuming this.el is the entity
var mesh = this.el.getObject3D('mesh');
var loader = new THREE.TextureLoader();
loader.load(url,
//onLoadCallback
function(texture) {
// apply the texture here
mesh.material.map = texture
},
// onProgressCallback - not sure if working
undefined,
// onErrorCallback
function(err) {
console.log("error:", err)
});
当然,您不需要立即应用纹理,您可以存储它(预加载)并在必要时使用它。
提琴here。