简体   繁体   中英

D3: data, enter, append pattern adds data to outer block

I'm using the D3 javascript library to render some basic web charts. I want to add three <path> elements to an <svg> block, but D3 is adding the elements to the end of the <html> block instead. Here's the complete html source:

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="d3.v2.js"></script>
<script>
var chartData = [ 1, 2, 3 ];
d3.select("html").select("body").append("svg")
  .data(chartData, function(d) { console.log("data d:", d); return d; })
  .enter()
    .append("path")
      .attr("d", function(d) { return d; });
</script>
</body>

Chrome's developer console shows the resulting html to be:

<html><head><meta charset="utf-8">
<style type="text/css"></style></head><body>
<script src="d3.v2.js"></script>
<script>
var chartData = [ 1, 2, 3 ];
d3.select("html").select("body").append("svg")
  .data(chartData, function(d) { console.log("data d:", d); return d; })
  .enter()
    .append("path")
      .attr("d", function(d) { return d; });
</script><svg></svg>
</body><path d="1"></path><path d="2"></path><path d="3"></path></html>

The <svg> block was created, but for some reason, the <path> blocks are outside of it. How can I correct this error, and put them inside the <svg> where they belong?

First off, you should have a high-level variable that only refers to the svg. Secondly, you should specify the height and width of the SVG when creating it. You don't need to specify a select of html , so:

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

Now you can use the svg variable to append paths. It is recommended that you group the paths together (hence the "g" appended first). And you should also do a selectAll for paths, because you want to bind the data you are adding to the path elements. So:

svg.append("g").selectAll("path")
    .data(chartData)
  .enter().append("path")
    .attr("d", function(d) { return d; });

I recommend the D3 tutorials here: http://alignedleft.com/tutorials/d3/

For future visitors having a similar issue:

It appears the difference of behavior in this case (and similar others) between select and selectAll hinges on the fact that selectAll creates a new group .

D3's selection object is an array of arrays with some additional special properties. Each array corresponds to a group of objects. One property of the group is the parentNode , which is the node from which the initial selectAll was executed.

When the outermost selection is a select , the root is implicitly the document's root node--in this case, html .

Since selectAll creates a new group within the selection for each match (or entry), each group is assigned as its parent the node from which it derives. With select , since no new group is created, the original parentNode for each group is preserved, even if it no longer accurately represents the parent of the nodes within the group .

The parentNode also appears (empirically) to be the node to which enter selections' append ed nodes are attached.

This is why select produced the observed behavior, and selectAll remedied the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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