【问题标题】:Error: <rect> attribute width: Expected length, "NaN". and <text> attribute dx: Expected length, "NaN"错误:<rect> 属性宽度:预期长度,“NaN”。和 <text> 属性 dx:预期长度,“NaN”
【发布时间】:2017-04-06 09:23:55
【问题描述】:

我想在 D3 中实现条形图,但我在 dx 轴上的值是日期类型,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;
                        });

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

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

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

    xScale.range() - rectPadding
    

    但是xScale.range() 返回一个数组,array - number 会给你一个NaN。而NaN 则无济于事...

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

    xScale.bandwidth();
    

    它不仅返回一个正确的数字,而且它也是您正在寻找的。​​p>

    这是您的代码更改:

    <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
    

    【讨论】:

    • 你能看到this的问题吗?我无法将我从您的回答中学到的知识应用到那个问题......
    • @ReemAl-Assaf 你确定const subgroups = data.slice(); 返回键(字符串)吗?在我看来,它返回了一个数组,其中包含 data 数组的最后 3 个对象。
    • 你完全正确!它切断了第一个元素,而不是标题行。我将其更改为 const subgroups = Object.keys(data[0]).slice(1) 并且可以正常工作。
    【解决方案2】:

    由于此代码(每行 20 像素)导致图表的元素高度太小时,我遇到了同样的错误

    document.getElementById('chart').style.height = (data.getNumberOfRows() * 20) + 'px';

    几个 data 项目很好,但是当我只有几个项目时,我得到了错误。所以我通过添加一些最小高度来修复它

    &lt;div id="chart" style="width: 100%; min-height: 100px"&gt;&lt;/div&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-15
      • 1970-01-01
      • 1970-01-01
      • 2020-10-22
      相关资源
      最近更新 更多