javascript - 错误 : <rect> attribute y: Expected length, "NaN"

标签 javascript d3.js

我正在尝试遵循这个例子 here对于 D3 堆积图。我已经在本地测试过它并且工作正常。 我已调整代码以匹配我的 csv 数据集,但不幸的是我在计算 y 和高度属性时遇到问题:

  • 错误:属性 y:预期长度,“NaN”。
  • 错误:属性高度:预期长度,“NaN”。

这是我改编的源代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Enterprise Elements Analysis - In/Out of Scope</title>
    <script src="http://d3js.org/d3.v4.min.js" charset="utf-8"></script>
    <style type="text/css">
        svg {
            font: 10px sans-serif;
            shape-rendering: crispEdges;
        }

        .axis path,
        .axis line {
            fill: none;
            stroke: #000;
        }

        path.domain {
            stroke: none;
        }

        .y .tick line {
            stroke: #ddd;
        }
  </style>
</head>
<body>
<script type="text/javascript">
// Our D3 code will go here
var ratData = [];

d3.csv("./etcounts.csv", function(d) {
    return {
        type: d.type,
        in_scope: +d.in_scope,
        out_scope: +d.out_scope
    };
}, function(error, rows) {
    data = rows;
    console.log(data);
    createVisualization();
});

function createVisualization() {
    // Setup svg using with margins
    var margin = {bottom: 75, left: 15, right: 85};
    var w = 200 - margin.left - margin.right;
    var h = 175 - margin.bottom;

    // get length of Array
    var arrayLength = data.length; // length of dataset
    var x_axisLength = 100; // length of x-axis in our layout
    var y_axisLength = 100; // length of y-axis in our layout

    var svg = d3.select("body")
        .append("svg")
        .attr("width", w + margin.left + margin.right)
        .attr("height", h + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + ",10)");

    // set up the properties for stack
    var stack = d3.stack()
        .keys(["In Scope", "Out Scope"])
        .order(d3.stackOrderDescending)
        .offset(d3.stackOffsetNone);

    // transpose your data using stack
    var series = stack(data);

    // view the stack
    console.log(series);

    // setup the Y scale
    var yScale = d3.scaleLinear()
        .domain([0, d3.max(series, function(d) {
            return d3.max(d, function(d) {
                return d[1];
            }); 
        })])
        .range([h, 0]);

    // Set some colors into an array
    var colors = ["#dfd6d6", "#d85f41"]; // choose colors

    // Create groups for each series, rect elements for each segment 
    var groups = svg.selectAll("g.type")
        .data(series)
        .enter().append("g")
        .attr("class", "type")
        .style("fill", function(d, i) {
            return colors[i]; // color the rectangles
        });

    // Create the rectangles
    var rect = groups.selectAll("rect")
        .data(function(d) {
            return d;
        })
        .enter()
        .append("rect")
        .attr("x", function(d,i) {
            return i * (x_axisLength/arrayLength) + 30; // Set x coordinate of rectangle to index of data value (i) *25
        })
        .attr("y", function(d) {
            return yScale(d[1]); // set base of rectangle
        })
        .attr("height", function(d) {
            return yScale(d[0]) - yScale(d[1]); // set height of rectangle
        })
        .attr("width", (x_axisLength/arrayLength) - 1) // set width of rectangle
        .on("mouseover", function() {
            tooltip.style("display", null); // hide tooltip
        })
        .on("mousemove", function(d) {
            var xPosition = d3.mouse(this)[0] - 15;
            var yPosition = d3.mouse(this)[1] - 25;
            tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")");
            tooltip.select("text").text(d.data.city + ": " + (d[1] - d[0])); // populate tooltip
        })
        .on("mouseout", function() {
            tooltip.style("display", "none");
        });

    // Draw legend
    var legend = svg.selectAll(".legend")
        .data(colors)
        .enter().append("g")
        .attr("class", "legend")
        .attr("transform", function(d, i) { return "translate(" + i * 50 + ", 110)"; });

    legend.append("rect")
        .attr("x", w - 70)
        .attr("width", 18)
        .attr("height", 18)
        .style("fill", function(d, i) {return colors.slice().reverse()[i];});

    legend.append("text")
        .attr("x", w - 49)
        .attr("y", 9)
        .attr("dy", ".35em")
        .style("text-anchor", "start")
        .text(function(d, i) { 
        switch (i) {
            case 0: return "In";
            case 1: return "Out";
        }
    });

    // Prep the tooltip bits, initial display is hidden
    var tooltip = svg.append("g")
        .attr("class", "tooltip")
        .style("display", "none");

    tooltip.append("text")
        .attr("x", 15)
        .attr("dy", "1.2em")
        .style("text-anchor", "middle")
        .attr("font-size", "12px");

    // Create y-axis
    svg.append("line")
        .attr("x1", 30)
        .attr("y1", 0)
        .attr("x2", 30)
        .attr("y2", 100)
        .attr("stroke-width", 2)
        .attr("stroke", "black");

    // y-axis label
    svg.append("text")
        .attr("class", "y label")
        .attr("text-anchor", "middle")
        .text("Elements")
        .attr("transform", "translate(20, 50) rotate(-90)")
        .attr("font-size", "14px")
        .attr("font-family", "'Open Sans', sans-serif");

    // Create x-axis
    svg.append("line")
        .attr("x1", 30)
        .attr("y1", 100)
        .attr("x2", 130)
        .attr("y2", 100)
        .attr("stroke-width", 2)
        .attr("stroke", "black");
}

</script>
</body>
</html>

我的数据集 (etcounts.csv) 在这里:

type,in_scope,out_scope
ERKRS,1,1
KKBER,6,5
KOKRS,1,31
BUKRS,78,143
VKORG,23,13
BWKEY,51,6
EKORG,5,6
WERKS,51,65
LGORT,9,180
SPART,9,3
VTWEG,2,0
PERSA,47,73

不幸的是,我的 D3/JS 技能没有达到标准,但我将不胜感激任何帮助。谢谢 - 约翰

最佳答案

代替

var stack = d3.stack()
    .keys(["In Scope", "Out Scope"]) <-- there is no key as such
    .order(d3.stackOrderDescending)
    .offset(d3.stackOffsetNone);

应该是:

var stack = d3.stack()
    .keys(["in_scope", "out_scope"])
    .order(d3.stackOrderDescending)
    .offset(d3.stackOffsetNone);

原因:您的 CSV “In Scope”、“Out Scope” 中没有键 应该是 "in_scope", "out_scope"

编辑

对于工具提示:

tooltip.select("text").text(d.data.city + ": "+ (d[1] - d[0]));

应该是

tooltip.select("text").text(d.data.type + ": "+ (d[1] - d[0]));

原因:您的 CSV 中没有 data.city

工作代码here

关于javascript - 错误 : <rect> attribute y: Expected length, "NaN",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46558265/

相关文章:

arrays - 如何访问 D3 中的嵌套数据值

javascript - 如何禁用 NodeJs Express 中的按钮?

javascript - 无法使用 forEach 动态创建数组

javascript - 在 native react 中启用/禁用返回键类型

d3.js - 更改 d3.js 地理 map 大小

javascript - 为什么条形图与 "inverted values"一起出现? d3.js

d3.js - .append() 根据条件不同的选择?

javascript - 在使用 ASP.Net 或 JavaScript 将图像复制到网站剪贴板方面需要帮助吗?

javascript - 使用 Mapbox GL JS 的动画标记

javascript - 构建连接到 SQL Server 的 Web 应用程序的步骤