如何重用自定义事件

时间:2015-02-18 14:25:16

标签: javascript d3.js

我正在使用D3构建可视化,这种可视化具有非常丰富的用户交互。目前我有一个支持以下事件的背景画布:

  • 点击
  • 双击
  • 长按
  • 拖动(用于平移)
  • zoom(捏+轮)

我正在尝试管理所有这些事件,而且我已经到了我开始为应用程序的不同部分重复我的代码的地步。例如,在应用程序中:

  1. 双击不应触发单击操作
  2. 双击也应忽略用户可能意外拖动的事实
  3. 所以我设计了一种方法来做到这一点。我现在感兴趣的是,是否有一种技术允许我重复使用我创建的事件(有点像你创建d3.behaviour.zoom并使用.call)。< / p>

    所以说明


    点击+双击

    我有一些行为可以在点击时启动计时器,这会在超时后触发单击行为。如果再次单击并且计时器仍然存在,则取消它并运行双击行为。我正在这样挂钩:

    d3.select(target)
      .append("circle")
      .on("click", function (d) {
        __onClick(d, this);
      });
    

    我之后定义了__onClick

    var __onClick = function (d) {
        var self = this;
    
        if (d3.event.defaultPrevented) return; // ignore drag
        d3.event.stopPropagation();            // prevent event bubbling
    
        // If we already have a timer then we need to execute
        // a double click behavior event
        if (self.__timer) {
            console.log("dblclick simulated");
            clearTimeout(self.__timer);
            self.__timer = null;
            self.DoADoubleClickThingy();
            return;
        }
    
        // Start a single click operation
        self.__timer = setTimeout(function () {
            console.log("click simulated");
            self.__timer = null;
            self.DoSingleClickThingy();
        }, 250);
    };
    

    所以我想我想知道,是否有可能创建类似以下的内容来注册新行为?我目前正在尝试查看D3代码但不太了解它是否足以知道这是否可行。

    var clicks = d3.behaviours.customDoubleClick
                 .clickSpeed(250)
                 .on("click", function() { self.DoSingleClickThingy(); })
                 .on("dblclick", function() { self.DoADoubleClickThingy(); });
    
    d3.select(target)
          .append("circle")
          .call(clicks);
    

2 个答案:

答案 0 :(得分:1)

您可以使用一个工厂函数,根据您想要的行为类型,返回一个安装相应处理程序的函数:

function mkClicks(type) {
  // figure out what "self" should be depending on type
  return function(sel) {
    sel.on("click", function() { self.DoSingleClickThingy(); })
       .on("dblclick", function() { self.DoADoubleClickThingy(); });
  }
}

d3.select(target)
  .append("circle")
  .call(mkClicks(typeA));

答案 1 :(得分:1)

再次阅读github上的zoom代码D3后,我意识到它并不像我想象的那么复杂 - 特别是当我意识到call实际上只是执行{ {1}}功能。这是我放在一起的解决方案,我希望将其放在github或类似的地方:

zoom