2016-01-21 54 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,其中包含更多關於此主題的內容。