ThreeJS:从场景中移除物体
我正在使用ThreeJS开发一个Web应用程序,显示实体列表,每个实体都有相应的“查看”和“隐藏”button。 例如entityName 查看隐藏 。 当用户点击查看button时,下面的函数被调用,实体在屏幕上绘制成功。
function loadOBJFile(objFile){ /* material of OBJ model */ var OBJMaterial = new THREE.MeshPhongMaterial({color: 0x8888ff}); var loader = new THREE.OBJLoader(); loader.load(objFile, function (object){ object.traverse (function (child){ if (child instanceof THREE.Mesh) { child.material = OBJMaterial; } }); object.position.y = 0.1; scene.add(object); }); } function addEntity(object) { loadOBJFile(object.name); }
并点击隐藏button,下面的函数被调用:
function removeEntity(object){ scene.remove(object.name); }
问题是,点击“ 隐藏”button后,实体不会从屏幕上移除。 我能做些什么来隐藏button的工作?
我做了小实验。 我添加了scene.remove(object.name);
在scene.add(object);
后面 在addEntity
函数中作为结果,当“View”button被点击时,没有实体绘制(如预期的)意思是scene.remove(object.name);
在addEntity
工作得很好。 但是我仍然无法弄清楚如何在removeEntity(object)中使用它。
此外,我检查了scene.children的内容,它显示:[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
完整的代码: http : //devplace.in/~harman/model_display1.php.html
请问,如果需要更多的细节。 我用ThreeJS的rev-59-dev和rev-60进行testing。
谢谢。 🙂
我认为看到你的使用addEntity和removeEntity代码将是有益的,但我的第一个想法是你实际设置object.name? 在scene.add(object)之前试试你的loader。 像这样的东西:
object.name = "test_name"; scene.add(object);
可能发生的情况是Object3D的默认“名称”是“”,所以当您调用removeEntity函数时,由于场景对象名称为“”
另外,我注意到你传入的object.name到你的loader? 这是你的URL存储资源? 如果是这样的话,我会build议使用Object3D内置的.userData方法来存储这些信息,并保留名称字段进行场景识别。
编辑:对新添加的代码的响应
首先要注意的是,在对象名中使用“/”并不是一个好主意,它似乎可以正常工作,但是您永远不知道某些algorithm是否会决定转义该string并破坏您的项目。
第二项是现在我已经看到你的代码,它实际上是直接发生了什么事情。 你的删除function试图按名称删除,你需要一个Object3D来删除。 尝试这个:
function removeEntity(object) { var selectedObject = scene.getObjectByName(object.name); scene.remove( selectedObject ); animate(); }
在这里你看到我在Three.js Scene
通过传入你的object标签的name
属性来查找你的Object3D
。 希望有所帮助
clearScene: function() { var objsToRemove = _.rest(scene.children, 1); _.each(objsToRemove, function( object ) { scene.remove(object); }); },
这个使用了unrecore.js来让场景中的所有孩子(除了第一个孩子)(这是我用来清除场景的代码的一部分)。 只要确保在删除后至less 渲染 一次场景,否则canvas不会改变! 不需要“特殊”obj国旗或任何类似的东西。
你也不要删除名字的对象,只是由对象本身,所以调用
scene.remove(object);
而不是scene.remove(object.name);
可以够了
PS: _.each
是underscore.js的一个函数
我有像你一样的问题。 我尝试这个代码,它工作得很好:当你创build你的对象把这个object.is_ob = true
function loadOBJFile(objFile){ /* material of OBJ model */ var OBJMaterial = new THREE.MeshPhongMaterial({color: 0x8888ff}); var loader = new THREE.OBJLoader(); loader.load(objFile, function (object){ object.traverse (function (child){ if (child instanceof THREE.Mesh) { child.material = OBJMaterial; } }); object.position.y = 0.1; // add this code object.is_ob = true; scene.add(object); }); } function addEntity(object) { loadOBJFile(object.name); }
然后你删除你的对象试试这个代码:
function removeEntity(object){ var obj, i; for ( i = scene.children.length - 1; i >= 0 ; i -- ) { obj = scene.children[ i ]; if ( obj.is_ob) { scene.remove(obj); } } }
尝试一下,告诉我是否有效,看来三个jsjoin到场景后不会识别这个对象。 但有了这个技巧,它的作品。
如果您的元素不是直接在您的场景上,请回到“家长”以将其删除
function removeEntity(object) { var selectedObject = scene.getObjectByName(object.name); selectedObject.parent.remove( selectedObject ); }
这个伟大的工作 – 我testing它,请为每个对象设置名称
在创build时将名称提供给对象
mesh.name = 'nameMeshObject';
并使用这个如果你有删除对象
delete3DOBJ('nameMeshObject'); function delete3DOBJ(objName){ var selectedObject = scene.getObjectByName(objName); scene.remove( selectedObject ); animate(); }
打开新的场景,添加对象
删除对象并创build新的
你可以使用这个
function removeEntity(object) { var scene = document.querySelectorAll("scene"); //clear the objects from the scene for (var i = 0; i < scene.length; i++) { //loop through to get all object in the scene var scene =document.getElementById("scene"); scene.removeChild(scene.childNodes[0]); //remove all specified objects }