d3.js使用动态缩放时的奇怪拖动行为

时间:2015-08-06 08:45:10

标签: javascript d3.js

我正在尝试构建一个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中看到它。

你有什么建议吗?是否有可能解决这个问题并以不同的方式移动几个节点?

2 个答案:

答案 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