简体   繁体   English

使用D3.js嵌套数据

[英]Nested data with D3.js

I'm trying to generate SVG elements using parent and nested data, but am having problems getting things to show up. 我正在尝试使用父级数据和嵌套数据生成SVG元素,但是在显示问题时遇到了问题。 This is very similar to Combining Parent and Nested Data with d3.js , which was very helpful, but doesn't quite address my issue. 这与将父数据和嵌套数据与d3.js结合非常相似,这非常有帮助,但是并不能完全解决我的问题。

For this example, I'm drawing SVG paths made up of multiple points. 对于此示例,我正在绘制由多个点组成的SVG路径。 I want to draw a tangent to each of the paths' line segments. 我想为每个路径的线段绘制切线。 It's mostly working, but I can't create groups for the tangent paths and instead they end up at the root of the SVG. 它通常可以正常工作,但是我无法为切线路径创建组,而是将它们最终置于SVG的根目录。 I'd like the structure to look like this: 我希望结构看起来像这样:

<svg width="100" height="100">

  <g id="0" class="linegroup">
    <g class="linepath">
      <path d="M0,0L10,10L20,20"></path>
    </g>
    <g class="tangentgroup">
      <path class="tan" d="M5,5L-5,15"></path>
      <path class="tan" d="M15,15L5,25"></path>
    </g>
  </g>

  <g id="1" class="linegroup">
    <g class="linepath">
      <path d="M30,30L40,40L50,50"></path>
    </g>
    <g class="tangentgroup">
      <path class="tan" d="M35,35L25,45"></path>
      <path class="tan" d="M45,45L35,55"></path>
    </g>
  </g>

</svg>

But instead, all of the tangent paths are being appended to the svg and I can't create the "tangentgroup" SVG group: 但是,相反,所有切线路径都附加到了svg上,而我无法创建“ tangentgroup” SVG组:

<svg width="100" height="100">

  <g id="0" class="linegroup">
    <g class="linepath">
      <path d="M0,0L10,10L20,20"></path>
    </g>
  </g>

  <g id="1" class="linegroup">
    <g class="linepath">
      <path d="M30,30L40,40L50,50"></path>
    </g>
  </g>

  <path class="tan" d="M5,5L-5,15"></path>
  <path class="tan" d="M15,15L5,25"></path>
  <path class="tan" d="M35,35L25,45"></path>
  <path class="tan" d="M45,45L35,55"></path>

</svg>

Here's is my code as it is currently. 这是我目前的代码。 I'm also open to suggestions on how to improve it in other ways. 我也愿意就如何以其他方式改进它提出建议。

// test data
var lines = [{
      id: 0,
      coordinates: [[0,0],[10,10],[20,20]]},
    {
      id: 1,
      coordinates: [[30,30],[40,40],[50,50]]
    }];

var diameter = 100;

var d3line = d3.svg.line();

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

// create groups for each line and its tangents
var linegroups = svg.selectAll('.linegroup')
    .data(lines)
  .enter().append('g')
    .attr('class', 'linegroup')
    .attr('id', function(d) { return d.id; });

// add the line path
linegroups.append('g')
  .attr('class', 'linepath')
.append('path')
  .attr("d", function(d) { return d3line(d.coordinates); });

/////// Problem section ////////

// create a group for the line's segment's tangents,
//  and create a tangent path for each segment
linegroups.each(function(line, i) {
  d3.selectAll(this)
      // The "tangentgroup" groups never show up
  .append('g')
    .attr('class', 'tangentgroup')
  .data(lineSegments(line.coordinates))
      // 'tan' paths get appended to parent svg, not to 'linegroup'.
  .enter().append('path')
    .attr('class', 'tan')
    .attr('d', function (d) {
      return d3line(tangentFromMidpoint(d));
    });
});

////////////////////////////////

// returns lineSegments, comprised of pairs of points
function lineSegments (coordinates) {
  return d3.range(coordinates.length - 1).map(function(i) {
    return [coordinates[i], coordinates[i + 1]];
  });
}

// returns a tangent line starting from the mid-point of the original line
function tangentFromMidpoint (line) {
  var p1 = line[0];
  var p2 = line[1];
  var midPoint = [(p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2];
  var tv = tangentVectors(p1,p2)[0];
  return [midPoint, [tv[0] + midPoint[0], tv[1] + midPoint[1]]];
}

// Returns both tangent vectors (not unit-vector) for a line
function tangentVectors (p1,p2) {
  // if we define dx=x2-x1 and dy=y2-y1,
  //  then the normals are (-dy, dx) and (dy, -dx)
  var dx = p2[0] - p1[0];
  var dy = p2[1] - p1[1];
  return [[-dy, dx, dy, -dx]];
}

The problem is that you're calling .data() without a .selectAll() first, but then operate on the .enter() selection. 问题在于您.selectAll()调用.data()而不使用.selectAll() ,然后再对.enter()选择进行操作。 The code should be 该代码应为

linegroups.each(function(line, i) {
  d3.select(this)
  .append('g')
    .attr('class', 'tangentgroup')
  .selectAll("path")
  .data(lineSegments(line.coordinates))
  .enter().append('path')
    .attr('class', 'tan')
    .attr('d', function (d) {
      return d3line(tangentFromMidpoint(d));
    });
});

Complete demo here . 在此处完成演示。 You don't even need the .each() though: 您甚至不需要.each()

linegroups.append('g')
   .attr('class', 'tangentgroup')
   .selectAll("path")
   .data(function(line) { return lineSegments(line.coordinates); })
   .enter().append('path')
   .attr('class', 'tan')
   .attr('d', function (d) {
     return d3line(tangentFromMidpoint(d));
   });

Complete demo here . 在此处完成演示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM