2016-03-14 39 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