在Three.js画布中添加图片后无法访问Mesh及图像数据丢失问题
Three.js 图片Mesh访问与图像丢失问题解决
问题分析
第一段代码:无法访问Mesh
TextureLoader.load()是异步方法,你把pic_mesh定义在加载完成的回调函数内部,这个变量的作用域仅限于回调函数,外部自然拿不到引用。而且你把load()的返回值(Texture对象)赋值给了pic1,但这不是Mesh,所以外部操作pic1也没用。
第二段代码:图像数据丢失
同样是异步加载的问题——你在调用load()后立刻设置colorSpace并创建材质、Mesh,但这时候图像还没加载完成,纹理数据是空的,导致渲染不出图像。TextureLoader.load()不会阻塞代码执行,后续代码会在图像加载完成前就跑完。
修正方案
方案1:解决第一段代码的Mesh访问问题
把Mesh变量提升到外部作用域,在回调里赋值,这样外部就能拿到引用:
let pic1_mesh; // 外部作用域声明Mesh变量 const img_loader = new THREE.TextureLoader() img_loader.load('pic.jpg', (texture) => { texture.colorSpace = THREE.SRGBColorSpace; const material = new THREE.MeshBasicMaterial({ map: texture, }); pic1_mesh = new THREE.Mesh(new THREE.PlaneGeometry(3, 3), material) scene.add(pic1_mesh) }); // 后续需要操作Mesh时,先判断是否已初始化(因为加载是异步的) // 比如在动画循环里: function animate() { requestAnimationFrame(animate); if (pic1_mesh) { pic1_mesh.rotation.x += 0.01; // 示例操作 } renderer.render(scene, camera); }
方案2:解决第二段代码的图像丢失问题
必须等纹理加载完成后,再创建材质和Mesh,确保纹理数据已就绪:
const pic1_geo = new THREE.PlaneGeometry(3, 3) const img_loader = new THREE.TextureLoader(); img_loader.load('pic1.jpg', (texture) => { texture.colorSpace = THREE.SRGBColorSpace; // 加载完成后再创建材质和Mesh const pic1_mat = new THREE.MeshBasicMaterial({ map: texture }) const pic1_mesh = new THREE.Mesh(pic1_geo, pic1_mat) scene.add(pic1_mesh) // 这里可以直接操作Mesh,比如旋转 pic1_mesh.rotation.x = -0.2; });
关键原理
Three.js加载纹理是异步操作,图像资源需要时间从网络/本地读取,所以所有依赖纹理的操作(设置colorSpace、创建材质、Mesh)必须放在加载完成的回调里,或者监听纹理的load事件。另外,变量作用域要注意,需要在外部访问的Mesh必须声明在回调函数的外部作用域。
内容的提问来源于stack exchange,提问作者Adeerlike
相关产品推荐
相关产品推荐

