javascript - 使用 D3.js 嵌套数据

标签 javascript d3.js svg nested

我正在尝试使用父数据和嵌套数据生成 SVG 元素,但在显示内容时遇到问题。这与Combining Parent and Nested Data with d3.js非常相似。 ,这非常有帮助,但并不能完全解决我的问题。

在此示例中,我绘制了由多个点组成的 SVG 路径。我想为每条路径的线段绘制一条切线。它大部分工作正常,但我无法为切线路径创建组,而是它们最终位于 SVG 的根部。我希望结构如下所示:

<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>

但是,所有切线路径都被附加到 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>

这是我当前的代码。我也愿意接受有关如何以其他方式改进它的建议。

// 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]];
}

最佳答案

问题是您首先在没有 .selectAll() 的情况下调用 .data(),然后对 .enter() 选择。代码应该是

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));
    });
});

完整演示 here 。不过,您甚至不需要 .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));
   });

完整演示 here .

关于javascript - 使用 D3.js 嵌套数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31977181/

相关文章:

javascript - 如何在jquery中不重复自己

javascript - 防止 d3 缩放将 svg 中的文本移动到与 svg 其余部分不同的位置

javascript - 在 D3.js 中向动画饼图添加新分段

javascript - 使用按点而不是按层组织数据的 d3 堆栈布局

python - 如何在 PDF 文档中插入 SVG 文件?

javascript - Angular 通用应用程序性能、APP_BOOTSTRAP_LISTENER、闪烁

javascript - $.post 数据数组

javascript - 当 fancybox 关闭时更改父页面上的图像 SRC

css - 更改数据 url 嵌入 SVG 图像的颜色

javascript - 隐藏 SVG 中的关键数据