【问题标题】:using d3 drag behavior's origin to create a "drag handle" for a tree node使用 d3 拖动行为的原点为树节点创建“拖动句柄”
【发布时间】:2014-07-11 16:08:24
【问题描述】:

我对 d3 还比较陌生,但我仍然会遇到一些让我难以理解的事情。

基本上,我有一棵带有可拖动节点的树。我想将节点的“拖动句柄”限制为只有圆圈,而不是圆圈和文本(以及我最终添加的任何其他内容)。

我知道这与在我的拖动行为中正确设置原点有关,但我似乎不太明白。

我在 stackoverflow 上找到了一些有用的信息(抱歉,我只能发布两个链接),查看 https://groups.google.com/forum/#!topic/d3-js/fjp1mpvVW1M 似乎我正在将拖动行为应用于 ag 容器的子元素,然后尝试将转换应用于其 g 容器。

我怎样才能做到这一点?

以下是相关代码:

var dragListener = d3.behavior.drag()
.origin(function () {
    var t = d3.select(this);
    return {
        x: t.attr("x") + d3.transform(t.attr("transform")).translate[0],
        y: t.attr("y") + d3.transform(t.attr("transform")).translate[1]
    };
})
.on("drag", function (d) {
    d.x0 += d3.event.dy;
    d.y0 += d3.event.dx;       
    //var node = d3.select(this);  //this works
    var node = d3.select(this.parentNode)  //this doesn't work
    node.attr("transform", "translate(" + d.y0 + "," + d.x0 + ")");
});

  var nodeEnter = node.enter().append("g")
  //.call(dragListener)  // this works
  .attr("class", "node")
  .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
  .on("click", click);

  nodeEnter.append("circle")
  .call(dragListener)  // this doesn't work
  .attr("r", 1e-6)
  .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });

这是一个小提琴: http://jsfiddle.net/tsmith77/4R3Cb/

更新

我无法让子组做我想做的事,但我通过拦截文本上的 mousedown 事件完成了我想做的事:

  nodeEnter.append("text")
  .on("mousedown", function (d) {
      d3.event.stopPropagation();
      })
  .on("click", function (d) {
      alert("text clicked");
  })

这可以防止文本成为拖动句柄,但仍然允许我在单击文本时执行操作。

【问题讨论】:

  • 您在这里遇到了麻烦,因为您使用了两种不同的方式来设置位置(transform 和设置元素的坐标),并且很容易在此处混淆。您是否正在寻找类似jsfiddle.net/4R3Cb/3 的内容
  • 谢谢拉斯。是的,类似的东西。只有在拖动圆圈时,我才会希望整个节点移动。我的 //this 有效代码和 //this doesn't work 代码之间唯一期望的行为差异是圆是我的用户可以“抓取”进行拖动的唯一元素。
  • 嗯,在您的示例中看起来已经是这种情况了?至少我不能把里面的文字拖进去。
  • 很抱歉未能传达我的愿望。我希望整个节点(文本和圆圈)在拖动时移动,但我希望圆圈是唯一可以用鼠标“抓住”的东西。原因是我有一个附加到文本的点击事件,我不希望用户在他们只想拖动时意外触发。
  • 这正是我在你的 jsfiddle 中得到的行为,以 this question 应该有用的一些抖动为模。

标签: javascript d3.js drag-and-drop drag


【解决方案1】:

在您的 CSS 中为与节点对应的文本设置以下行:

  pointer-events: none;

(一种方法是为所有此类文本分配一个名为“node-label”的类,然后像上面一样定义该类的属性“pointer-events”)

这将防止通过抓取文本进行拖动。

我还会给你两个活生生的例子。他们处理强制布局,而不是像你的情况那样处理树,但没关系,原理是一样的。

example 1 - 可以通过抓住圆圈和标签来拖动

example 2 - 只抓取圆圈即可拖动

它们之间的区别只有一行:

  pointer-events: none;

【讨论】:

  • 这将使它非常容易,但不幸的是,我在文本中附加了一个点击事件。基本上我希望文本是我的点击元素,我的圆圈是我的拖动和折叠元素。
  • 您应该在问题中说明这一点。请参阅 (stackoverflow.com/help/mcve)。
猜你喜欢
  • 1970-01-01
  • 2015-04-05
  • 1970-01-01
  • 2013-04-03
  • 2021-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-25
相关资源
最近更新 更多