Simple D3 demo not working with altered structure

2020-05-04 08:53发布

问题:

I was following the official tutorial. Since the structure was pretty rudimentary I decided to do a cleaner one:

<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<head>
<title>D3</title>
<style>
    .chart div {
        font: 10px sans-serif;
        background-color: steelblue;
        text-align: right;
        padding: 3px;
        margin: 1px;
        color: white;
    }
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

    var data = [4, 8, 15, 16, 23, 42];

    var x = d3.scale.linear()
        .domain([0, d3.max(data)])
        .range([0, 420]);

    d3.select(".chart")
        .selectAll("div")
        .data(data)
    .enter().append("div")
        .style("width", function(d) { return d * 10 + "px"; })
        .text(function(d) { return d; });

</script>
</head>
<body>

    <div class="chart"></div>

</body>
</html>

But that is not working. This is the error I'm getting:

d3.html:20 Uncaught TypeError: Cannot read property 'linear' of undefined

I've found in D3 api that the method scale.linear is now called using scaleLinear.

The output error disappeared but I still can't see anything, while copypasting the example with scale.linear old method works.

What I'm doing wrong?

回答1:

Your script is on the head, and it's being parsed before the div with a class "chart" being generated .

Just move all your script to the end of the body, after the div you are selecting:

.chart div {
        font: 10px sans-serif;
        background-color: steelblue;
        text-align: right;
        padding: 3px;
        margin: 1px;
        color: white;
    }
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<div class="chart"></div>
<script>
  var data = [4, 8, 15, 16, 23, 42];

    var x = d3.scaleLinear()
        .domain([0, d3.max(data)])
        .range([0, 420]);

    d3.select(".chart")
        .selectAll("div")
        .data(data)
    .enter().append("div")
        .style("width", function(d) { return d * 10 + "px"; })
        .text(function(d) { return d; });
  </script>
</body>

If you want to keep the script in the head, for whatever reason, just change d3.select(".chart") for d3.select("body"):

div {
        font: 10px sans-serif;
        background-color: steelblue;
        text-align: right;
        padding: 3px;
        margin: 1px;
        color: white;
    }
<head>
<title>D3</title>
<style>
    .chart div {
        font: 10px sans-serif;
        background-color: steelblue;
        text-align: right;
        padding: 3px;
        margin: 1px;
        color: white;
    }
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

    var data = [4, 8, 15, 16, 23, 42];

    var x = d3.scaleLinear()
        .domain([0, d3.max(data)])
        .range([0, 420]);

    d3.select("body")
        .selectAll("div")
        .data(data)
    .enter().append("div")
        .style("width", function(d) { return d * 10 + "px"; })
        .text(function(d) { return d; });

</script>
</head>
<body>
</body>