dat.gui: Обновить значения выпадающего списка для контроллера?

Я пытаюсь выяснить, возможно ли обновить только значения раскрывающегося списка для контроллера dat.gui.

var gui = new dat.GUI();
gui.add(this, 'toggle').onChange( updateToggle );
gui.add(item, 'template', [ 'A', 'B', 'C', 'D' ]).onChange( updateTemplate );

Когда переключатель изменен, я хочу изменить параметры шаблона:

if (startRibbon) {
     gui.__controllers[1].options(['A', 'B']);
} else {
     gui.__controllers[1].options(['A', 'B', 'C', 'D']);
};

Это изменяет значения, но создает новый контроллер шаблона с новым индексом (удаляя предыдущий) и делая его неработоспособным в следующий раз. Он также помещает новый в конец списка контроллеров.

Прежде чем я добавлю больше кода, чтобы попытаться преследовать новый модифицированный/новый контроллер, я подумал, что должен посмотреть, есть ли у кого-нибудь лучший способ.


person choppingblock    schedule 15.08.2013    source источник


Ответы (3)


Просто обновите html-содержимое раскрывающегося списка.

function updateDropdown(target, list){   
    innerHTMLStr = "";
    for(var i=0; i<list.length; i++){
        var str = "<option value='" + list[i] + "'>" + list[i] + "</option>";
        innerHTMLStr += str;        
    }

    if (innerHTMLStr != "") target.domElement.children[0].innerHTML = innerHTMLStr;
}

dropdown = gui.add(MyObject, 'Values', ['A', 'B']);

updateDropdown(dropdown , ['A', 'B', 'C', 'D']);
person Flemming    schedule 03.05.2018

Я пытался сделать то же самое. Мое решение — использовать onChange для удаления и добавления контроллера. Поскольку это толкает его на дно и нарушает порядок, я не могу просто сделать то, что вы сделали напрямую. Я также должен удалить и добавить обратно в seq все те, которые находятся под ним.

Или если контроллеров слишком много, было бы удобнее просто иметь функцию удалить все и добавить все обратно для таких случаев.

Редактируя мое решение для вашего примера, оно будет примерно таким...

var arr_template = [ 'A', 'B', 'C', 'D' ];

var gui = new dat.GUI();
gui.add(this, 'toggle').onChange( updateToggle );  // controller 0
gui.add(item, 'template', arr_template).onChange( updateTemplate ); // controller 1
gui.add(extra,'hello'); // controller 2

function updateTemplate()
{
  if (startRibbon) {
     arr_template = [ 'A', 'B'];
  } else {
     arr_template = [ 'A', 'B', 'C', 'D' ];
  }

  // remove controllers >= 1 in reverse order
  gui.__controllers[2].remove();
  gui.__controllers[1].remove();

  // add back in order
  gui.add(item, 'template', arr_template).onChange( updateTemplate ); // controller 1
  gui.add(extra,'hello'); // controller 2
}
person EDM    schedule 09.05.2014
comment
Вау, эта проблема была исправлена ​​в последних версиях? Или это единственный способ? - person Luis B; 04.08.2015

Вы можете использовать функцию options. Я кодирую это для примера. Я надеюсь, что вы можете адаптировать его.

var controller;

var config = {
  'value': '1',
  'changeValues': function () {
    controller.options( [ 'A', 'B', 'C' ] );
    controller.updateDisplay();
  }
};

var gui = new dat.GUI();
gui.add( config, 'changeValues' );
controller = gui.add( config, 'value', [ '1', '2', '3' ] );

Здесь вы можете найти активный код.

person rvcristiand    schedule 31.07.2020
comment
это работает только в первый раз. После этого он выдает ошибку DOM: Uncaught DOMException: не удалось выполнить «removeChild» на «узле»: удаляемый узел не является дочерним элементом этого узла. - person Felix Turner; 12.10.2020