2017-08-04 66 views
1

我開始一個新的項目,主要目的是學習一些基本的d3.js。這裏是我的玩具問題:我想繪製一個帶有幾個矩形的交互式流程圖,當用戶懸停/點擊一個矩形時,我想用指向場景中其他矩形的箭頭顯示相關性。我還想在其他地方顯示一些文本,並以此用戶操作爲條件。箭頭和文字下面的點擊和懸停

最終目標是這樣的:

enter image description here

這裏是我的出發點,通過一些基本的教程啓發:

的index.html

<!DOCTYPE html> 
<html> 
    <head> 
     <script src="https://d3js.org/d3.v4.min.js"></script> 
    </head> 
    <body> 
     <script src="script.js"></script> 
    </body> 
</html> 

script.js

var s = 50; 
var w = 200; 
var h = 100; 

var jsonBoxes = [ 
    {"name": "Box A", "x_axis": s, "y_axis": s, "width": w, "content": "content of Box A", "depends" : "Box C"}, 
    {"name": "Box B", "x_axis": w + 2*s, "y_axis": s, "width": w, "content": "content of Box B", "depends" : "Box D"}, 
    {"name": "Box C", "x_axis": 2*(w + s) + s, "y_axis": s, "width": w, "content": "content of Box C", "depends" : "Box D" }, 
    {"name": "Box D", "x_axis": s, "y_axis": 2*s +h, "width": w, "content" : "content of Box D" , "depends": "Box F"}, 
    {"name": "Box E", "x_axis": w + 2*s, "y_axis": 2*s+h, "width": w, "content": "content of Box E", "depends" : "Box F" }, 
    {"name": "Box F", "x_axis": 2*(w + s) + s, "y_axis": 2*s+h, "width": w, "content": "content of Box F", "depends" : "Box A" }]; 

var svgContainer = d3.select("body").append("svg") 
            .attr("width", 800) 
            .attr("height", 300); 

var rectangles = svgContainer.selectAll("rect") 
          .data(jsonBoxes) 
          .enter() 
          .append("rect"); 

var rectanglesAttributes = rectangles 
         .attr("x", function (d) { return d.x_axis; }) 
         .attr("y", function (d) { return d.y_axis; }) 
         .attr("width", function (d) { return d.width; }) 
         .attr("height", 100) 
         .style("fill", function(d) { return "Cornsilk"; }); 

var p = d3.select("body").selectAll("p") 
    .data(jsonBoxes) 
    .enter() 
    .append("p") 
    .text(function(d) { return d.name + ": " + d.content; }); 

有人可以說明(/指向我)處理懸停或點擊並在此基礎上生成內容(箭頭,文本)的一般過程嗎? PS:我很樂意R以更合適的格式預處理數據。我使用yaml作爲輸入格式,並且根據需要似乎很容易生成json。 d3映射和交互性是我是一個全新手的地方。

回答

1

第一:在<svg>,你有<text>而不是<p>,令人沮喪的是,它不會包裝自己。要包裝文字,請查看Mike Bostock's Block

總體上,點擊功能採用這種形式:

selection.on('click', function (data, index) { 
    stuff(); 
}) 

徘徊在click的地方使用mouseovermouseout。對於這個問題,看起來click將是一個明智的選擇,以顯示箭頭和mouseover'其他文字'。在你的情況下,它可能是這個樣子:

rectangles.on('click', function (d, i) { //1 
    d3.select('svg').append('path').attr('d', pathString); //2 
    d3.selectAll('rect').filter(function (k, j) { 
     return k.name == d.depends; //3 
    }).each(function() { 
     d3.select(this).on('click')(); //4 
    }); 
}).on('mouseover', function (d, i) { //5 
    d3.select('text#moreinfo').text(d.extraInfo); 
}); 

箭頭將需要path元素,除非添加polygon元素,每頭他們不會有頭。

  1. 將點擊事件附加到每個矩形。
  2. 追加到svg a path元素(它是一行)。
  3. 從它的名字找到必備課程的rect
  4. 爲這些(或單數)前提矩形中的每一個調用click事件。請注意,因爲每個點擊事件都是以這種方式設置的,所以這實際上是一個遞歸調用,它將爲鏈中的每個先決條件繪製箭頭。
  5. 附加一個鼠標懸停處理程序,它將更改「其他文本」text元素的文本,只要您先前創建該元素。

爲了使箭頭變得很酷和彎曲,就像在圖像中一樣,您需要計算路徑的控制點。 Here是一個很酷的圖形來解釋如何使用CubicBézier曲線的路徑。你應該能夠用一些基本的幾何圖形來計算控制點。

我建議首先真正熟悉svg

+0

謝謝。我看到了文本環繞的塊,但它是一個相當複雜的例子,因爲它是條形圖的一部分。我希望能找到更簡單的東西,只需要一個'div'或者更遠一點的東西(也許與svg分開)。關於箭頭和貝塞爾曲線,根據我見過的例子(可摺疊樹等),我會認爲d3可以爲我製作漂亮的路徑。話雖如此,由於我的佈局是靜態的,我可以簡單地在自己的繪畫中繪製箭頭,並且在點擊/懸停時只有d3纔會改變顏色。 – baptiste

+0

這似乎是一個很酷的想法,如果你願意,我肯定會動態地做到這一點。我坦率地不太熟悉[樹](https://github.com/d3/d3-hierarchy/blob/master/README.md#treemap)(我不知道它們適合你的情況有多好) ,但是你可以做一些類似[this](http://bl.ocks.org/robschmuecker/7880033)的東西,但是要製作'節點的矩形,並把'text'放在它的上面。 –

+0

同樣對於'div'的想法,你可以使用'd3'作爲'DOM'操縱器,就像jQuery一樣,語句如:'d3.select('body')。append('div').text('foo' );'這肯定會使包裝變得更容易; –