最近我一直在使用ThreeJS模型。 我设法实现了一个自定义函数,它可以加载每个所需的.obj一次,如果有更多的对象使用相同的模型,则克隆它们而不是再次加载它们。
问题是我需要以特定方式为每个克隆的网格设置动画。
我创建了一个对象数组,其中包含需要动画化的每个网格的函数,这些网格将在需要时循环并执行。问题是,由于某种原因,只有第一个模型实际上是动画的。
这是我用于动画网格物体的代码。
function loadModel(m){
for(var i = 0; i<objects.length; i++){
if(m.name === objects[i].modelData.model){
mesh = m.mesh.clone();
mesh.position.x = objects[i].positionX * distanceAmplifier;
mesh.position.y = objects[i].positionY * distanceAmplifier;
mesh.position.z = objects[i].positionZ * distanceAmplifier;
mesh.scale.set(1000,1000,1000);
//Adding animation
animations.push(function(){
mesh.rotation.z += 1.0005;
});
scene.add(mesh);
}
}
}
在动画中我这样做:
if(animations.length === objects.length){
animations.map(function(anim){
anim();
});
}
如果我加载不同的obj网格,则每个网格的第一个实例都是动画的,但不是克隆本身。
我希望有同样问题的人可以帮我解决这个问题
答案 0 :(得分:1)
对我来说看起来像是一个范围问题。我认为它不是正在动画的克隆的第一个实例,而是 last
在此处检查您的代码:
animations.push(function(){
mesh.rotation.z += 1.0005;
});
您正在做的是将匿名函数推送到数组中。但是这个功能在被推动时不会立即执行,它只是坐在那里等待被叫。当它最终被执行时,mesh
早已不再是将函数推入数组时所做的一切。由于您在循环范围之外的某处声明mesh
变量,因此对mesh
的每一个引用都指向完全相同的变量。
有两种方法可以解决这个问题。一种简单的方法是为循环的每次迭代创建一个新的mesh
变量,而不是不必要地引用一个超出当前范围的变量:
var newMesh = m.mesh.clone(); // declare a brand new var instead of reusing 'mesh'
...
animations.push(function(){
newMesh.rotation.z += 1.0005;
});
如果你有某种疯狂的理由在你的循环范围内实际使用mesh
,你可以&#34;关闭&#34;它在执行for循环时的值,而不是让它在以后被推迟。这被称为&#34;关闭&#34;并且在JavaScript中理解是重要的事情:
// Create an anonymous function and pass it 'mesh'
// Then execute it immediately to capture the current 'mesh' value
(function(_mesh){
animations.push(function(){
_mesh.rotation.z += 1.0005;
});
})(mesh);
注意现在不仅创建匿名函数,而且立即执行,并传递mesh
变量以同时捕获它的值
(function(){console.log("Hello.");})(); // this is executed immediately!
这有一个名字:&#34;立即调用函数表达式&#34;。它听起来完全是什么 - 声明一个函数然后立即执行它。这是创建闭包的常用方法。
我建议您阅读有关范围和闭包在JavaScript中如何工作的一些内容:
祝你好运!