D3-在DOM元素之间绘制路径 [英] D3 - Drawing a path between DOM elements

查看:181
本文介绍了D3-在DOM元素之间绘制路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个平行坐标图.每个圈子是一个特定的品牌,每个品牌在每一列中都有一个圈子:

I'm creating a parallel coordinates chart. Each circle is a particular brand, and every brand has one circle in each column:

当用户将鼠标悬停在一个圆圈上时,我想画一条将该圆圈与同一品牌的其他三个圆圈相连的路径.问题在于圆的X位置是随机的,因此我必须使用圆的修改后的cx值(而不是数据)绘制直线.

When the user hovers over a circle, I would like to draw a path connecting that circle to the other three circles of the same brand. The issue is that the X position of the circles is random, so I have to draw the line using the circle's modified cx value (and not the data).

为方便起见,我将所有四个品牌圈子归入了各自的g元素:

Conveniently, I have all four brand circles grouped in their own g elements:

<g class="line-group">
    <circle r="5" cx="340.48700997553686" cy="0" data-brand="Brand X"></circle>
    <circle r="5" cx="916.9181438059958" cy="59.347826086956466" data-brand="Brand X"></circle>
    <circle r="5" cx="1589.2772695723352" cy="229.1306884480747" data-brand="Brand X"></circle>
    <circle r="5" cx="2272.275506967826" cy="0" data-brand="Brand X"></circle>
</g>

我可以抓取元素,并按d3.line()喜欢的方式对坐标进行分组,但是它形成一条连接每个点的线.

I can grab the elements, and group the coordinates in a way d3.line() likes, but it makes one line that connects every point.

var line = d3.svg.line()
               .interpolate('basis');

var circles = d3.selectAll('.line-group').selectAll('circle'),
          circleCoords = [];

      circles.forEach( function(d) {
        console.log(circles);
        for ( i = 0; i < d.length; i++ ) {
          var cx = d3.select(d[i]).attr('cx'),
              cy = d3.select(d[i]).attr('cy');

          circleCoords.push([cx, cy]);
        }
      });

      lineGroup.append('path')
             .attr({
               'd' : line( circleCoords )
             });

如何构造此结构,以便可以获取每个圈子组(在g.line-group内部的同一品牌的四个圈子)的cx和cy值?

How do I structure this so I can grab the cx and cy values of each circle group (the four circles of the same brand inside of g.line-group)?

我可能必须创建一个自定义d属性,如下所示(伪代码):

I probably have to make a custom d attribute, something like this (pseudocode):

path.attr('d', function(d) { 
                  return 'M ' + /* cx of circle 1 */ + ' ' + /* cy of circle 1 */ + 
                    ' L ' + /* cx of circle 2 */ + ' ' + /* cy of circle 2 */ + 
                    ' L ' + /* cx of circle 3 */ + ' ' + /* cy of circle 3 */ + 
                    ' L ' + /* cx of circle 4 */ + ' ' + /* cy of circle 4 */ + ' Z';
                })

我相信所有组件都在那里,我似乎无法找到正确组合它们的方法.如果有人有任何想法,将不胜感激!

I believe all the pieces are there, I just can't seem to find a way to put it together correctly. If anyone has any ideas, it would be greatly appreciated!

:添加了行定义.

推荐答案

您的选择有误(我看不到您的行定义,请不要忘记它):

You has the wrong selection (I can't see your line definition, don't forget it):

var svg = d3.selectAll("svg")
var circles = svg.selectAll('.line-group').selectAll("circle"),
// or var circles = svg.selectAll('.line-group > circle'),

          circleCoords = [];

      circles.forEach( function(d) {
        for ( i = 0; i < d.length; i++ ) {
          var cx = d3.select(d[i]).attr('cx'),
              cy = d3.select(d[i]).attr('cy');

          circleCoords.push([cx, cy]);
        }
        console.log(circleCoords);  
      });

      var line = d3.svg.line()

      svg.append('path')
             .attr({
               'd' : line( circleCoords )
             });

此处为工作代码

别忘了样式. 您需要确定每个".line-group",否则D3将选择所有".line-group"类,可能会添加id属性.-

Don't forget styles. You need to identify each '.line-group' or D3 will select all '.line-group' class, may adding id attribute.-

在您的情况下,您有多个品牌",就像这样:

In your case you have multiple "Brands", like so:

<svg>
<g class="line-group">
    <circle r="5" cx="10" cy="110" data-brand="Brand-X"></circle>
    <circle r="5" cx="30" cy="120" data-brand="Brand-X"></circle>
    <circle r="5" cx="150" cy="30" data-brand="Brand-X"></circle>
    <circle r="5" cx="290" cy="40" data-brand="Brand-X"></circle>
</g>

<g class="line-group">
    <circle r="5" cx="10" cy="10" data-brand="Brand-Y"></circle>
    <circle r="5" cx="30" cy="20" data-brand="Brand-Y"></circle>
    <circle r="5" cx="150" cy="130" data-brand="Brand-Y"></circle>
    <circle r="5" cx="290" cy="140" data-brand="Brand-Y"></circle>
</g>
</svg>

您需要重构代码:

var svg = d3.selectAll("svg")
var circles = svg.selectAll('.line-group').selectAll("circle"),
          circleCoords = [];
var line = d3.svg.line()

// circles.length give you .line-group's count or brand's count:

   for (j=0; j<circles.length; j++) {
       circles[j].forEach( function(d) {     // forEach brand draw a line
          var cx = d.getAttribute('cx'),
              cy = d.getAttribute('cy');
          circleCoords.push([cx, cy]);
       })
       svg.append('path')
          .attr({ 'd' : line( circleCoords )  })
          .attr("id","id_"+j);
       circleCoords = [];
   };

这是工作代码

这篇关于D3-在DOM元素之间绘制路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆