我正在尝试构建一个d3图(目前只有未连接的节点)来处理相对较小的节点值。出于这个原因,我使用线性比例,对输入值进行动态反应并相应地对它们进行缩放:
var xScale = d3.scale.linear().range([0, width]);
var yScale = d3.scale.linear().range([height, 0]);
[...]
xScale.domain(d3.extent(layout, function (d){ return d.x; }));
yScale.domain(d3.extent(layout, function (d){ return d.y; }));
在当前版本中(您可以在此处找到它:https://jsfiddle.net/mn1wmbe3/6/)单个节点的拖动和值更改工作正常。这是我用来移动节点的代码:
node.filter(function(d) { return d.selected; })
.each(function(d) {
d.x = xScale.invert(d3.event.x);
d.y = yScale.invert(d3.event.y);
})
.attr("cx", xScale(d.x))
.attr("cy", yScale(d.y));
如其他示例所示,为了能够同时移动多个节点,我需要将拖动移动的相对坐标(d3.event.dx
)添加到每个选定的节点值。像这样:
node.filter(function(d) { return d.selected; })
.each(function(d) {
d.x += xScale.invert(d3.event.dx);
d.y += yScale.invert(d3.event.dy);
})
.attr("cx", xScale(d.x))
.attr("cy", yScale(d.y));
但是,这种行为并不像预期的那样,并且将节点移动到远处。您可以在行动here中看到它。
你有什么建议吗?是否有可能解决这个问题并以不同的方式移动几个节点?
答案 0 :(得分:0)
您只需要进行一些小的更改即可使工作正常。首先,从以下位置更改拖动事件:
d.x += xScale.invert(d3.event.dx);
d.y += yScale.invert(d3.event.dy);
要:
d.x = xScale.invert(d3.event.x);
d.y = yScale.invert(d3.event.y);
事情将不再像以前那样跳来跳去。但是,如果增加半径的大小,您会注意到,当您第一次开始拖动时,对象将跳转到鼠标位置的中心位置。这是因为您现在需要指定原点函数。更改此代码:
d3.behavior.drag()
.on("drag", function(d) {
对此:
.call(d3.behavior.drag()
.origin(function(d){return {x:xScale(d.x), y:yScale(d.y)};})
.on("drag", function(d) {
有了这个,当你拖动它时会记住偏移量。现在情况会很好。
现在要相对移动多个节点,您可以编写自己的dx,dy
函数。只需在dragstart
上记录对象的坐标,然后在dx,dy
上计算drag
,并将这些值添加到要移动的其他节点。
答案 1 :(得分:0)
我明白了。基本上,错误是使用动态缩放:
insert(_:atIndex:)
由于我的测试数据,这导致域名出现:
xScale.domain(d3.extent(layout, function (d){ return d.x; }));
yScale.domain(d3.extent(layout, function (d){ return d.y; }));
如果以这种方式移动节点,那么表现完全正常:
xScale.domain(-2, 1);
yScale.domain(-1, 0);
但是,当尝试通过向它们添加增量距离(d.x = xScale.invert(d3.event.x);
d.y = yScale.invert(d3.event.y);
)来移动节点时,比例的反转会导致意外结果。这样做的原因是d3.event.dx
返回xScale.invert(1)
这一事实,当添加到原始值时,会产生意外结果。
<强>解决方案强>
我使用的解决方法计算数据的最小值和最大值之间的距离,并将域从零设置为此值:
-1.994