2013-11-20 49 views
1

我使用d3.layout.force可视化图形结构。 我想要节点拖拽功能和平移功能。 (通过'平移',我的意思是像谷歌地图的行为。)实现平移,同时保持节点在d3强制布局中可拖动

如几个d3的例子所示,节点可以通过nodes.call(force.drag)拖动。 并且可以通过d3.behavior.drag执行平移。

但是,它似乎不能同时使用。

下面是一个代码示例:

var width = 400, height = 300; 
var svg = d3.select('body').append('svg').attr({width: width, height: height}); 

var nodes = [{}, {}, {}, {}]; 
var links = [ 
    {source: 1, target: 0}, 
    {source: 2, target: 0}, 
    {source: 0, target: 3} 
]; 

var nodeSel = svg.selectAll('circle') 
    .data(nodes).enter().append('circle') 
    .attr('r', 10).attr('fill', 'black'); 
var linkSel = svg.selectAll('line').data(links).enter().append('line') 
    .attr('stroke', 'black'); 

var force = d3.layout.force() 
    .size([width, height]) 
    .nodes(nodes).links(links) 
    .linkDistance(80) 
    .charge(-300) 
    .on('tick', function() { 
     linkSel 
      .attr('x1', function(d) { return d.source.x; }) 
      .attr('y1', function(d) { return d.source.y; }) 
      .attr('x2', function(d) { return d.target.x; }) 
      .attr('y2', function(d) { return d.target.y; }); 
     nodeSel 
      .attr('cx', function(d) { return d.x; }) 
      .attr('cy', function(d) { return d.y; }); 
    }); 

nodeSel.call(force.drag); 


/* This block of codes spoils force.drag */ 
/* **************************************** 
var drag = d3.behavior.drag(); 
var viewBoxX = 0, viewBoxY = 0; 
drag.on('dragstart', function() { 
    console.log('new dragstart is called'); 
}).on('drag', function() { 
    viewBoxX -= d3.event.dx; 
    viewBoxY -= d3.event.dy; 
    svg.attr('viewBox', [viewBoxX, viewBoxY, width, height].join(' ')); 
}).on('dragend', function() { 
    console.log('new dragend is called'); 
}); 
svg.call(drag); 
**************************************** */ 


force.start(); 

(工作之一是上的jsfiddle:http://jsfiddle.net/dersinces/hzL8T/1/

该代码仅允许节点拖动,而不是平移。 激活底部的代码块(第36行)启用平移,但它使节点不可复制。

如何在保持节点可拖动的同时实现图形平移?

+0

您只需要缩放行为(它也拖动)。见例如[这里](http://jsfiddle.net/nrabinowitz/QMKm3/)。 –

+0

谢谢,@LarsKotthoff!我会看看'd3.behavior.zoom'。 – dersinces

回答

2

这里是你如何能做到这:Demo

的想法是把它有它包含了节点,以便节点仍然可以接收mouseevents的区域下的拖动行为的区域。

// First append the area where the dragging will happen. 
svg.append('rect') 
    .classed('bg', true) 
    .attr('stroke', 'transparent') 
    .attr('fill', 'transparent') 
    .attr('x', 0) 
    .attr('y', 0) 
    .attr('width', width) 
    .attr('height', height) 
    .call(drag); 


// Then add the area which will contain the nodes. 
var nodeArea = svg.append('g') 
       .classed('node-area', true); 
+0

该演示似乎无法解决我的问题。节点不可拖动,平移不适用于链接。也许你的观点是插入不可见的矩形(与@ LarsKotthoff示例相同的想法)。但是,这种平移方式受到矩形大小的限制。如果可能,我想要另一个解决方案。 – dersinces

+0

嘎!对于那个很抱歉。我链接到一个较旧的演示版本。我现在指出的版本应该可以工作。 –

+0

抱歉迟到回复@musically_ut。你的新演示完美无缺!你解决了我的问题。真的感谢! – dersinces

相关问题