2016-01-21 53 views
2

下面是我的JS代码在D3中实现力布局图的摘录。我有两个要求:单击事件导致拖动事件以及强制布局图

  1. 点击一个节点应该引起从后台检索并添加到图形子节点(这工作)。

  2. 拖动一个节点时,它应该在拖动停止时保持固定。当同一节点与CMDCTRL密钥组合点击时,应再次释放该节点。 (这个工程,以及)

我的问题是,当我点击一个节点,进一步扩大它的节点变成固定以及。因此,无意中点击导致拖动事件被调用。但是,拖动不会导致节点进一步扩展(由于if (d3.event.defaultPrevented) return;)。

function visNetwork(graph_id) { 

    this.graph_id = graph_id; 

    /* Some code removed for brevity */ 

    var dragstart = function(d) { 
     console.log('Detected drag...'); 
     d3.event.sourceEvent.preventDefault(); 
     d3.select(this).classed("fixed", d.fixed = true); 
    }; 

    // set up the D3 visualisation in the specified element 
    var w = 2000, 
     h = 2000; 

    var vis = d3.select("#svg-container") 
     .append("svg") 
     .attr("id", this.graph_id) 
     //necessary to convert the SVG to canvas 
     .attr("version", 1.1) 
     .attr("xmlns", "http://www.w3.org/2000/svg") 
     //better to keep the viewBox dimensions with variables 
     .attr("viewBox", "0 0 " + w + " " + h) 
     .attr("preserveAspectRatio", "xMidYMid meet"); 

    var force = d3.layout.force() 
     .charge(-1500) 
     .linkDistance(150) 
     .size([w, h]) 
     .gravity(.1); 

    var drag = force.drag() 
     .on("dragstart", dragstart); 

    var nodes = force.nodes(), 
     links = force.links(); 

    var update = function() { 
     var link = vis.selectAll("line") 
      .data(links, function(d) { 
       return d.source.id + "-" + d.target.id; 
      }); 

     link.enter().insert("line", "g") 
      .attr("id", function(d) { 
       return d.source.id + "-" + d.target.id; 
      }) 
      .attr("class", "link") 
      .attr("stroke", "#ccc"); 

     link.exit().remove(); 

     var node = vis.selectAll("g.node") 
      .data(nodes, function(d) { 
       return d.id; 
      }); 

     var nodeEnter = node.enter().append("g") 
      .attr("class", "node") 
      .on('click', function(d, i) { 
       if (d3.event.defaultPrevented) { 
        console.log('Ignoring click event...'); 
        return; 
       } 
       console.log('Captured click event...'); 

       //Release fixed node when CTRL or CMD key is pressed 
       if (d3.event.ctrlKey || d3.event.metaKey) { 
        d3.select(this).classed("fixed", d.fixed = false); 
        return; 
       } 
       modifyGraph(d.id, d3.event); 
       }) 
       .call(drag); 

     nodeEnter.append("svg:circle"); /* Code removed for brevity */ 

     nodeEnter.append("svg:text"); /* Code removed for brevity */ 

     node.exit().remove(); 

     force.on("tick", function() { /* Code removed for brevity */ }); 
     // Restart the force layout. 
     force.start(); 
    }; 
    update(); 
} 
+2

您使用的是哪个版本的d3?请阅读[这个答案]的评论(http://stackoverflow.com/a/19951105/1006854)。 –

+0

你能模拟出一个能够显示你问题基础的小提琴吗? – thatOneGuy

+0

@mef我正在使用D3.js版本3.5.12 –

回答

0

在这种情况下,你可以达到你想要的东西,通过固定点一次“拖”时,忽略“的dragstart” altoghether。

请在评论部分阅读@mef链接的question and answers,其中包含更多关于此主题的内容。