错误:<rect>属性width:预期长度,“NaN”。和<text>属性dx:预期长度,“NaN”

时间:2016-11-22 15:56:18

标签: javascript d3.js

我想在D3中实现条形图,但我在dx轴上的值是Date类型,D3库应该接受的数据类型,但它似乎给我一个这样的错误:属性宽度:预期长度,“NaN”。 这是我的代码:

<html> 
 <head> 
    <meta charset="utf-8">         
    <title>a bar graph</title> 
 </head> 
 <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="http://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.range()- 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.range() - 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> 
</html>

另一个错误:属性dx:预期长度,“NaN”。我认为它来自乐队规模,但在使用官方介绍之后,它仍然无法奏效。 官方介绍:

var x = d3.scaleBand()
    .domain(["a", "b", "c"])
    .range([0, width]);

因此,当我想调用代码时,我认为应该在我的粘贴代码中使用它:

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.range() - rectPadding)/2;
                        })
                       .attr("dy",function(d){
                                return 20;
                        })
                       .text(function(d){
                                return d;
                        });

但它似乎给了我两个错误。我是初学者。非常感谢你!

1 个答案:

答案 0 :(得分:5)

现在,对于矩形的宽度和文本的dx,您正在使用:

xScale.range() - rectPadding

但是xScale.range()会返回一个数组,array - number会给你一个NaN。并且你没有NaN ...

而不是xScale.range(),它将返回一个数组,你应该使用:

xScale.bandwidth();

这不仅会返回正确的数字,而且也是您正在寻找的数字。

以下是您更改的代码:

<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:您不需要rectPadding。只需在波段范围内设置填充:

var xScale = d3.scaleBand()
    .domain(d3.range(dataset.length))
    .range([0, width-padding.left-padding.right])
    .padding(0.2);//some value here