如何在强制布局中拖动时将svg元素捕捉到网格

时间:2016-03-09 20:39:11

标签: d3.js svg

我有this d3.js强制布局,其中节点是带有相关文本的矩形。每当拖动节点时,位置都是固定的,就像在迈克的example中一样。

我希望节点在拖动时捕捉到不可见的网格。这样他们整齐地对齐。因此我将此添加到拖动事件中:

var grid = 50;
d3.select(this)
  .attr("x", function(d) { return Math.round(d3.event.x/grid)*grid; })
  .attr("y", function(d) { return Math.round(d3.event.y/grid)*grid; });

不知怎的,这没有按预期工作。我想这与力布局的滴答功能有关。但我不确定,因此force.stop(),force.start()调用以查看是否有帮助。

我还尝试将rect和text嵌套在g元素中,并使用transform(translate)来定位节点。但也没有成功。

1 个答案:

答案 0 :(得分:3)

https://jsfiddle.net/e5fxojvm/

function dblclick(d) {
  d3.select(this).classed("fixed", d.fixed = false);
}

function dragstarted(d) {
  d3.select(this)
    .classed("fixed", d.fixed = true);
}

function dragged(d,i) {
  //force.stop();
  var grid = 50;

  var nx = Math.round(d3.event.x/grid)*grid;
  var ny = Math.round(d3.event.y/grid)*grid;

  d.px = nx;
  d.py = ny;
}

function dragended(d) {
  //force.start();
  console.log(this);
}

节点的坐标取自dx和dy,用于节点数组中的每个数据点,因此,虽然您更新了屏幕上元素的x和y属性,但是下一个tick会将其重置为dx和dy,从而产生这种小动作你在你的演示中看到了(虽然在节点修复后它不再移动)

您需要对节点位置数据(d.x和d.y)进行离散化 - 不仅仅是节点DOM元素的位置属性,对于固定节点而言,这似乎是通过d.px和d.py(前一个节点坐标)完成的。 tick中的固定节点似乎通过将它们设置为d.px和d.py(https://github.com/mbostock/d3/blob/master/d3.js#L6299)来计算d.x和d.y?