【问题标题】:Method for disabling a button in dat.gui?在 dat.gui 中禁用按钮的方法?
【发布时间】:2014-06-27 23:07:28
【问题描述】:

我正在尝试找出一种方法来轻松禁用/启用 dat.gui 中的按钮。

我设置了 dat.gui 来控制动画。当动画结束时,我希望禁用“播放”按钮。我尝试向按钮的 DOM 元素添加“禁用”属性,但在设置此属性后单击按钮时,我仍然看到相应的函数触发。

我目前的方法如下:

  1. 在dat.gui界面中找到与按钮对应的li元素
  2. 创建一个新的半透明黑色 DOM 元素,并将其添加到 li 元素中以使按钮的内容变灰。
  3. 在绑定到该按钮的函数中,检查按钮内是否存在这个“已禁用”的 DOM 元素,如果存在,则不要执行该函数的其余部分。

这是一个 hack,我很想知道是否有一些方法可以禁用 dat.gui 中内置的按钮,或者我不知道的更好的方法。

【问题讨论】:

    标签: javascript dat.gui


    【解决方案1】:

    在 dat.GUI 中,FunctionController 类负责按钮。如果您查看its source code,那里没有条件逻辑。控制器将监听按钮上的click 事件,并始终在单击时调用该函数。这意味着您不会从这里的库中获得任何帮助 - 您需要在处理程序中检查按钮是否被禁用。大致如下:

    // Find the GUI controller listening to given property on given object
    function getController(gui, object, property)
    {
      for (var i = 0; i < gui.__controllers.length; i++)
      {
        var controller = gui.__controllers[i];
        if (controller.object == object && controller.property == property)
          return controller;
      }
      return null;
    }
    
    ...
    
    object.button = function()
    {
      // Don't do anything if the button is disabled
      if (getController(gui, this, "button").domElement.hasAttribute("disabled"))
        return;
    
      alert("Button clicked");
    };
    gui.add(object, "button");
    
    ...
    
    // Disable button
    getController(gui, object, "button").domElement.setAttribute("disabled", "");
    

    请注意,dom.GUI 中的禁用元素没有特殊样式,您必须为此添加自己的样式。鉴于您在按钮的情况下看到的是属性标签而不是实际按钮,这不会很简单 - 我认为您必须将 disabled 属性放在 controller.domElement.parentNode 而不是 controller.domElement .然后你应该可以使用选择器[disabled] &gt; .property-name 来设置你的样式。

    编辑:您实际上可以通过扩展 FunctionController 以更通用的方式执行此操作:

    function blockEvent(event)
    {
      event.stopPropagation();
    }
    
    Object.defineProperty(dat.controllers.FunctionController.prototype, "disabled", {
      get: function()
      {
        return this.domElement.hasAttribute("disabled");
      },
      set: function(value)
      {
        if (value)
        {
          this.domElement.setAttribute("disabled", "disabled");
          this.domElement.addEventListener("click", blockEvent, true);
        }
        else
        {
          this.domElement.removeAttribute("disabled");
          this.domElement.removeEventListener("click", blockEvent, true);
        }
      },
      enumerable: true
    });
    

    这将向控制器添加一个属性disabled,该属性将捕获click 事件,因此不会触发按钮处理程序。然后禁用按钮变得更简单:

    getController(gui, object, "button").disabled = true;
    

    并且按钮处理程序可以保持不变,它根本不会被禁用的按钮触发。

    【讨论】:

    • 谢谢弗拉基米尔。这与我目前使用的方法基本相同(除了我向 DOM 添加一个元素,而不是一个属性,但想法是相同的)。正如我所怀疑的,使用 dat.gui 代码可能不是一个简单的方法来处理这个问题。
    • @JeffFohl:我添加了一个更通用的解决方案 - 您可以扩展 FunctionController,这将允许您保持其他代码(如按钮处理程序)不变。
    • 啊 - 伟大的解决方案弗拉基米尔。谢谢!
    【解决方案2】:

    这是我能想到的最直接的方法来禁用 dat GUI 的单个元素:

    let gui = new dat.GUI();  
    let uiElement = gui.add(myObject, 'myPropertyName');
     
    uiElement.__li.style = "opacity: 0.5; filter: grayscale(100%) blur(1px); pointer-events: none;"; 
    

    旧浏览器可能不支持pointer-events: none;,因此您可以选择添加:

    disableAll(uiElement.__li);
    
    function disableAll(element){    
        for( var i = 0; i < element.childNodes.length; ++i){
            let elt = element.childNodes[i];
            disableAll(elt);
            elt.disabled = true;
        }
    }
    

    这可能看起来很“hacky”,但在官方dat GUI API 中没有这样的功能,即使它在那里,也很可能会做一些非常相似的事情。

    最后,通过 API 你可以完全删除一个元素:

    uiElement.remove();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-24
      • 1970-01-01
      相关资源
      最近更新 更多