ThreeJS: удалить объект из сцены
Я использую ThreeJS для разработки веб-приложения, которое отображает список сущностей, каждый из которых имеет соответствующие кнопки "Вид" и "Скрыть"; например 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
. Но все же я не могу понять, как использовать его в removeEntity (object).
Кроме того, я проверил содержимое scene.children, и он показывает: [Object Object], [Object Object], [Object Object], [Object Object], [Object Object], [Object Object]
Полный код: http://devplace.in/~harman/model_display1.php.html
Пожалуйста, спросите, требуется ли более подробная информация. Я тестировал с rev-59-dev и rev-60 от ThreeJS.
Спасибо.:)
Ответы
Ответ 1
Я думаю, что ваше использование для 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
. Надеюсь, что поможет
Ответ 2
clearScene: function() {
var objsToRemove = _.rest(scene.children, 1);
_.each(objsToRemove, function( object ) {
scene.remove(object);
});
},
это использует undescore.js для итерации по всем дочерним элементам (кроме первого) в сцене (это часть кода, которую я использую для очистки сцены). просто убедитесь, что вы визуализируете сцену по крайней мере один раз после, потому что в противном случае холст не изменяется! Нет необходимости в специальном флагов obj или что-то в этом роде.
Также вы не удаляете объект по имени, просто самим объектом, поэтому вызываете
scene.remove(object);
вместо scene.remove(object.name);
может быть достаточно
PS: _.each
является функцией underscore.js
Ответ 3
У меня была та же проблема, что и у вас. Я пробую этот код, и он работает отлично:
Когда вы создаете свой объект, поставьте этот 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 не распознают объект после добавления в сцену. Но с этим трюком это работает.
Ответ 4
Если ваш элемент не находится на вашей сцене, вернитесь к родительскому, чтобы удалить его.
function removeEntity(object) {
var selectedObject = scene.getObjectByName(object.name);
selectedObject.parent.remove( selectedObject );
}
Ответ 5
ЭТО БОЛЬШАЯ РАБОТА - я тестирую это
поэтому, пожалуйста, НАЗВАНИЕ НАЗНАЧЕНИЯ для каждого объекта
укажите имя объекта при создании
mesh.name = 'nameMeshObject';
и использовать это, если вы удаляете объект
delete3DOBJ('nameMeshObject');
function delete3DOBJ(objName){
var selectedObject = scene.getObjectByName(objName);
scene.remove( selectedObject );
animate();
}
открыть новую сцену, добавить объект
![открыть новую сцену, добавить объект]()
удалить объект и создать новый
![удалить объект и создать новый]()
Ответ 6
Вы можете использовать этот
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
}