2016-03-14 36 views
1

我希望在一些圓圈(或者在這種情況下,圓圈的某些角)之間生成線條,以便將鼠標懸停在一個圓上可以看到指向所有其他圓圈的線條。我的問題是,我似乎無法找到如何使用d3訪問每個圈/組的points的相關部分。每個點的多條線

我相信我需要改變數據結構points或使用d3的each,但我不明白它是如何完成的。下面是一個工作示例,但是從最後24行代碼中可以明顯看出,這不是(或者不應該)是可擴展的。

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 
    line{opacity: 0.0;stroke : blue;} 
    g:hover line{opacity: 1.0;} 
</style> 

<body> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.15/d3.min.js"></script> 
    <script> 
    var svg = d3.select("body").append("svg") 
     .attr("width", 500) 
     .attr("height", 500) 

    var x = d3.scale.linear().domain([0,1]).range([0, 500]); 
    var y = d3.scale.linear().domain([0,1]).range([500, 0]); 

    d3.csv('input_data.csv', function(error,data){ 
     if (error) throw error; 

     var circles = svg.selectAll("g") 
     .data(data).enter().append("g") 
     .attr("id",function(d,i){return "group"+i;}) 
     .append("circle") 
     .attr('cx',function(d){return x(d.x);}) 
     .attr('cy',function(d){return y(d.y);}) 
     .attr('r',50); 

     //generating points which I want to connect with one line 
     //per 2 xy coordinates 
     var points = []; 
     for (var i=0;i<data.length;i++){  
     points.push([]) 
     for (var j = 0; j < data.length; j++) { 
      points[i].push(
      {'xval':[data[i].x,data[j].x], 
      'yval':[data[i].y,data[j].y]} 
     ); 
     } 
     } 
     //attempt at drawing some of these lines 
     svg.selectAll("#group0").selectAll("line") 
     .data(points).enter().append("line") 
     .attr("x1",function(d,i){return x(d[0].xval[0]);}) 
     .attr("x2",function(d,i){return x(d[0].xval[1]);}) 
     .attr("y1",function(d,i){return y(d[0].yval[0]);}) 
     .attr("y2",function(d,i){return y(d[0].yval[1]);}); 
     svg.selectAll("#group1").selectAll("line") 
     .data(points).enter().append("line") 
     .attr("x1",function(d,i){return x(d[1].xval[0]);}) 
     .attr("x2",function(d,i){return x(d[1].xval[1]);}) 
     .attr("y1",function(d,i){return y(d[1].yval[0]);}) 
     .attr("y2",function(d,i){return y(d[1].yval[1]);}); 
     svg.selectAll("#group2").selectAll("line") 
     .data(points).enter().append("line") 
     .attr("x1",function(d,i){return x(d[2].xval[0]);}) 
     .attr("x2",function(d,i){return x(d[2].xval[1]);}) 
     .attr("y1",function(d,i){return y(d[2].yval[0]);}) 
     .attr("y2",function(d,i){return y(d[2].yval[1]);}); 
     svg.selectAll("#group3").selectAll("line") 
     .data(points).enter().append("line") 
     .attr("x1",function(d,i){return x(d[3].xval[0]);}) 
     .attr("x2",function(d,i){return x(d[3].xval[1]);}) 
     .attr("y1",function(d,i){return y(d[3].yval[0]);}) 
     .attr("y2",function(d,i){return y(d[3].yval[1]);}); 

    }); 
    </script> 
</body> 

此代碼應該是我想給定的文件input_data.csv什麼(N幾乎)最小的獨立例如:

x,y 
0.5,1.0 
0.0,0.5 
1.0,0.5 
0.5,0.0 

回答

1

與目前的方法保持一致,怎麼樣:

circles.each(function(d0){ 
    var self = this; 
    var group = d3.select(self.parentNode); 
    circles.each(function(d1){ 
     if (self !== this){ 
     group.append("line") 
      .attr("x1",function(d,i){return x(d0.x);}) 
      .attr("x2",function(d,i){return x(d1.x);}) 
      .attr("y1",function(d,i){return y(d0.y);}) 
      .attr("y2",function(d,i){return y(d1.y);}); 
     } 
    }); 

Full code here


而不是預先繪製所有行,你可能想考慮在mouseover上繪製它們並在mouseout上移除它們。隨着點數的增加,內存可能會更加容易。這看起來像:

// draw circles... 
    .on('mouseover', function(d0){ 
     var self = this; 
     var group = d3.select(self.parentNode); 
     circles.each(function(d1){ 
     if (self !== this){ 
      group.append("line") 
      .attr("x1",function(d,i){return x(d0.x);}) 
      .attr("x2",function(d,i){return x(d1.x);}) 
      .attr("y1",function(d,i){return y(d0.y);}) 
      .attr("y2",function(d,i){return y(d1.y);}); 
     } 
     }); 
    }) 
    .on('mouseout', function(d){ 
     var self = this; 
     var group = d3.select(self.parentNode); 
     group.selectAll('line').remove(); 
    }); 

的完整代碼here

+0

謝謝,我會看看它。在一個側面說明中,「保持你當前的方法論」是指我預先繪製它,還是暗示你會做其他事情?如果是這樣,那麼糟糕的代碼會突出什麼? –

+0

@ M.T,我指的是預繪圖。查看更新以回答在鼠標懸停和跳出時進行的操作。 – Mark