我使用ThreeJS开发一个显示实体列表的Web应用程序,每个实体都有相应的" View"和"隐藏"按钮;例如 entityName 查看隐藏 。当用户点击查看按钮时,会调用以下功能并成功在屏幕上绘制实体。
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);
}
点击隐藏按钮,会调用以下功能:
function removeEntity(object){
scene.remove(object.name);
}
问题是,单击隐藏按钮后,实体不会在加载后从屏幕中删除。如何使隐藏按钮起作用?
我做了小实验。我在scene.remove(object.name);
scene.add(object);
函数后面addEntity
添加scene.remove(object.name);
,结果是"查看"单击按钮,没有实体绘制(按预期),意味着addEntity
在{{1}}内工作得很好。但我仍然无法弄清楚如何在removeEntity(object)中使用它。
另外,我检查了scene.children的内容,它显示:[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
完整代码:http://devplace.in/~harman/model_display1.php.html
如果需要更多详细信息,请询问。我用revJ-59-dev和rev-60测试了ThreeJS。
感谢。 :)
答案 0 :(得分:41)
我认为看到你对addEntity和removeEntity代码的使用会有所帮助,但我首先想到的是你实际设置了object.name吗?在scene.add(object)之前尝试加载你的加载器;像这样的东西:
object.name = "test_name";
scene.add(object);
可能发生的事情是Object3D的默认“名称”为“”,因此当您调用removeEntity函数时,由于场景对象名称为“”
而失败另外,我注意到你将object.name传递给你的加载器?这是您将URL存储到资源的位置吗?如果是这样,我建议使用Object3D的内置.userData方法来存储该信息,并保留名称字段以用于场景识别。
编辑:对新添加的代码的响应
首先要注意的是,在对象名称中包含“/”并不是一个好主意,它似乎工作正常,但你永远不知道某些算法是否会决定转义该字符串并破坏你的项目。
现在第二项是我见过你的代码,它实际上是直截了当的。您的删除功能正在尝试按名称删除,您需要删除一个Object3D。试试这个:
function removeEntity(object) {
var selectedObject = scene.getObjectByName(object.name);
scene.remove( selectedObject );
animate();
}
您可以在此处通过传递对象标记的Object3D
属性来查看Three.js Scene
中的name
。希望有所帮助
答案 1 :(得分:11)
clearScene: function() {
var objsToRemove = _.rest(scene.children, 1);
_.each(objsToRemove, function( object ) {
scene.remove(object);
});
},
这使用了unexcore.js来对场景中的所有子节点(除了第一个)进行迭代(它是我用来清除场景的代码的一部分)。只需确保渲染场景至少删除一次,否则画布不会改变!没有必要使用“特殊”obj标志或类似的东西。
此外,您不是按名称删除对象,只是按对象本身删除,因此调用
scene.remove(object);
而不是scene.remove(object.name);
可以就够了
PS:_.each
是underscore.js
答案 2 :(得分:3)
这项工作很棒 - 我测试了它 所以,请为每个对象设置名称
在创建时为对象命名
mesh.name = 'nameMeshObject';
并在必须删除对象时使用此
delete3DOBJ('nameMeshObject');
function delete3DOBJ(objName){
var selectedObject = scene.getObjectByName(objName);
scene.remove( selectedObject );
animate();
}
答案 3 :(得分:2)
使用时:scene.remove(object); 该对象已从场景中删除,但与它的碰撞仍处于启用状态!
要同时删除与对象的碰撞,可以使用(对于数组): objectsArray.splice(i,1);
示例:
for (var i = 0; i < objectsArray.length; i++) {
//::: each object ::://
var object = objectsArray[i];
//::: remove all objects from the scene ::://
scene.remove(object);
//::: remove all objects from the array ::://
objectsArray.splice(i, 1);
}
答案 4 :(得分:1)
我遇到了和你一样的问题。我尝试这个代码,它的工作正常: 在创建对象时,将此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);
}
}
}
尝试并告诉我这是否有效,似乎三个js在添加到场景后无法识别该对象。但有了这个技巧,它就可以了。
答案 5 :(得分:1)
如果你的元素没有直接在你的场景上,请回到Parent删除它
function removeEntity(object) {
var selectedObject = scene.getObjectByName(object.name);
selectedObject.parent.remove( selectedObject );
}
答案 6 :(得分:1)
我开始将其保存为一个函数,并根据需要对其进行调用:
function Remove(){
while(scene.children.length > 0){
scene.remove(scene.children[0]);
}
}
现在可以调用Remove()了;适当的功能。
答案 7 :(得分:1)
答案 8 :(得分:1)
我改进了 removeObject3D 的 Ibrahim 代码,添加了一些几何或材料检查
removeObject3D(object) {
if (!(object instanceof THREE.Object3D)) return false;
// for better memory management and performance
if (object.geometry) {
object.geometry.dispose();
}
if (object.material) {
if (object.material instanceof Array) {
// for better memory management and performance
object.material.forEach(material => material.dispose());
} else {
// for better memory management and performance
object.material.dispose();
}
}
if (object.parent) {
object.parent.remove(object);
}
// the parent might be the scene or another Object3D, but it is sure to be removed this way
return true;
}
答案 9 :(得分:0)
我来晚了,但在阅读了答案后,需要进一步澄清。
function removeEntity(object) {
// scene.remove(); it expects as a parameter a THREE.Object3D and not a string
scene.remove(object.name); // you are giving it a string => it will not remove the object
}
function removeObject3D(object3D) {
if (!(object3D instanceof THREE.Object3D)) return false;
// for better memory management and performance
object.geometry.dispose();
if (object.material instanceof Array) {
// for better memory management and performance
object.material.forEach(material => material.dispose());
} else {
// for better memory management and performance
object.material.dispose();
}
object.removeFromParent(); // the parent might be the scene or another Object3D, but it is sure to be removed this way
return true;
}
答案 10 :(得分:-8)
您可以使用此
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
}