Error: attribute width: Expected length, “NaN”. and attribute dx: Expected length, “NaN”

后端 未结 1 632
感情败类
感情败类 2021-01-04 05:59

I want to implement a bar chart in D3, but my values on the dx axis are of type Date, data type which the D3 library should accept, but it seems to give me an error like th

相关标签:
1条回答
  • 2021-01-04 06:30

    Right now, for the width of the rectangles and the dx of the texts, you're using:

    xScale.range() - rectPadding
    

    But xScale.range() returns an array, and array - number will give you a NaN. And you're not getting anywhere with a NaN...

    Instead of xScale.range(), which will return an array, you should use:

    xScale.bandwidth();
    

    Which not only returns a proper number, but it's also what you're looking for.

    Here is your code with that change:

    <style>
      .axis path,
      .axis line {
        fill: none;
        stroke: black;
        shape-rendering: crispEdges;
      }
      
      .axis text {
        font-family: sans-serif;
        font-size: 11px;
      }
      
      .MyRect {
        fill: steelblue;
      }
      
      .MyText {
        fill: white;
        text-anchor: middle;
      }
    </style>
    
    <body>
      <script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
      <script>
        var width = 400;
        var height = 400;
    
        var svg = d3.select("body")
          .append("svg")
          .attr("width", width)
          .attr("height", height);
    
        var padding = {
          left: 30,
          right: 30,
          top: 20,
          bottom: 20
        };
    
        var dataset = [10, 20, 30, 40, 33, 24, 12, 5];
    
    
        var xScale = d3.scaleBand()
          .domain(d3.range(dataset.length))
          .range([0, width - padding.left - padding.right]);
    
    
        var yScale = d3.scaleLinear()
          .domain([0, d3.max(dataset)])
          .range([height - padding.top - padding.bottom, 0]);
    
        var xAxis = d3.axisBottom()
          .scale(xScale)
    
        var yAxis = d3.axisLeft()
          .scale(yScale)
    
        var rectPadding = 4;
    
        var rects = svg.selectAll(".Myrect")
          .data(dataset)
          .enter()
          .append("rect")
          .attr("class", "Myrect")
          .attr("transform", "translate(" + padding.left + "," + padding.top + ")")
          .attr("x", function(d, i) {
            return xScale(i) + rectPadding / 2;
          })
          .attr("y", function(d) {
            return yScale(d);
          })
          .attr("width", xScale.bandwidth() - rectPadding)
          .attr("height", function(d) {
            return height - padding.top - padding.bottom - yScale(d);
          });
        var texts = svg.selectAll(".MyText")
          .data(dataset)
          .enter()
          .append("text")
          .attr("class", "MyText")
          .attr("transform", "translate(" + padding.left + "," + padding.top + ")")
          .attr("x", function(d, i) {
            return xScale(i) + rectPadding / 2;
          })
          .attr("y", function(d) {
            return yScale(d);
          })
          .attr("dx", function() {
            return (xScale.bandwidth() - rectPadding) / 2;
          })
          .attr("dy", function(d) {
            return 20;
          })
          .text(function(d) {
            return d;
          });
    
        svg.append("g")
          .attr("class", "axis")
          .attr("transform", "translate(" + padding.left + "," + (height - padding.bottom) + ")")
          .call(xAxis);
    
        svg.append("g")
          .attr("class", "axis")
          .attr("transform", "translate(" + padding.left + "," + padding.top + ")")
          .call(yAxis);
      </script>
    </body>


    PS: You don't need rectPadding. Just set the padding in the band scale:

    var xScale = d3.scaleBand()
        .domain(d3.range(dataset.length))
        .range([0, width-padding.left-padding.right])
        .padding(0.2);//some value here
    
    0 讨论(0)
提交回复
热议问题