gpt4 book ai didi

javascript - d3.js 如何从数组中绘制堆叠的水平条?

转载 作者:行者123 更新时间:2023-11-29 19:29:59 26 4
gpt4 key购买 nike

我试图让这个堆叠水平条的特定示例在浏览器中独立工作:http://tributary.io/inlet/4966973 .我知道之前有人问过有关此代码的问题,但从未将其用于工作示例。当我在浏览器中运行下面的代码时(即在支流站点之外),我得到这个错误:'错误:属性转换的无效值=“翻译(0,NaN)”'。为什么代码不能在浏览器中运行?是否缺少某些元素?

<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<div id="container">

<section id="display" style="width: 1038px;">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:xlink="http://www.w3.org/1999/xlink" class="tributary_svg" width="677" height="533"></svg></section>
</div>
<script>
/*modified from Mike Bostock at http://bl.ocks.org/3943967 */

var data = [
{"key":"FL", "pop1":3000, "pop2":4000, "pop3":5000},
{"key":"CA", "pop1":3000, "pop2":3000, "pop3":3000},
{"key":"NY", "pop1":12000, "pop2":5000, "pop3":13000},
{"key":"NC", "pop1":8000, "pop2":21000, "pop3":11000},
{"key":"SC", "pop1":30000, "pop2":12000, "pop3":8000},
{"key":"AZ", "pop1":26614, "pop2":6944, "pop3":30778},
{"key":"TX", "pop1":8000, "pop2":12088, "pop3":20000}
];

var n = 3, // number of layers
m = data.length, // number of samples per layer
stack = d3.layout.stack(),
labels = data.map(function(d) {return d.key;}),

//go through each layer (pop1, pop2 etc, that's the range(n) part)
//then go through each object in data and pull out that objects's population data
//and put it into an array where x is the index and y is the number
layers = stack(d3.range(n).map(function(d) {
var a = [];
for (var i = 0; i < m; ++i) {
a[i] = {x: i, y: data[i]['pop' + (d+1)]};
}
return a;
})),

//the largest single layer
yGroupMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y; }); }),
//the largest stack
yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); });

var margin = {top: 40, right: 10, bottom: 20, left: 50},
width = 677 - margin.left - margin.right,
height = 533 - margin.top - margin.bottom;

var y = d3.scale.ordinal()
.domain(d3.range(m))
.rangeRoundBands([2, height], .08);

var x = d3.scale.linear()
.domain([0, yStackMax])
.range([0, width]);

var color = d3.scale.linear()
.domain([0, n - 1])
.range(["#aad", "#556"]);

var xx = margin.top;

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

var layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer")
.style("fill", function(d, i) { return color(i); });

layer.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("y", function(d) { return y(d.x); })
.attr("x", function(d) { return x(d.y0); })
.attr("height", y.rangeBand())
.attr("width", function(d) { return x(d.y); });

var yAxis = d3.svg.axis()
.scale(y)
.tickSize(1)
.tickPadding(6)
.tickValues(labels)
.orient("left");

svg.append("g")
.attr("class", "y axis")
.call(yAxis);
</script

</body>

最佳答案

您发现自己是一个相当有趣的问题,它可能与我们在另一个类似问题中发现的问题有关。参见 this answer .

为了检验理论,这里是您的代码复制并粘贴到 Stack Overflow 片段中。第一个使用的是 d3 3.2.8,似乎工作正常。

/*modified from Mike Bostock at http://bl.ocks.org/3943967 */

var data = [
{"key":"FL", "pop1":3000, "pop2":4000, "pop3":5000},
{"key":"CA", "pop1":3000, "pop2":3000, "pop3":3000},
{"key":"NY", "pop1":12000, "pop2":5000, "pop3":13000},
{"key":"NC", "pop1":8000, "pop2":21000, "pop3":11000},
{"key":"SC", "pop1":30000, "pop2":12000, "pop3":8000},
{"key":"AZ", "pop1":26614, "pop2":6944, "pop3":30778},
{"key":"TX", "pop1":8000, "pop2":12088, "pop3":20000}
];

var n = 3, // number of layers
m = data.length, // number of samples per layer
stack = d3.layout.stack(),
labels = data.map(function(d) {return d.key;}),

//go through each layer (pop1, pop2 etc, that's the range(n) part)
//then go through each object in data and pull out that objects's population data
//and put it into an array where x is the index and y is the number
layers = stack(d3.range(n).map(function(d) {
var a = [];
for (var i = 0; i < m; ++i) {
a[i] = {x: i, y: data[i]['pop' + (d+1)]};
}
return a;
})),

//the largest single layer
yGroupMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y; }); }),
//the largest stack
yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); });

var margin = {top: 40, right: 10, bottom: 20, left: 50},
width = 677 - margin.left - margin.right,
height = 533 - margin.top - margin.bottom;

var y = d3.scale.ordinal()
.domain(d3.range(m))
.rangeRoundBands([2, height], .08);

var x = d3.scale.linear()
.domain([0, yStackMax])
.range([0, width]);

var color = d3.scale.linear()
.domain([0, n - 1])
.range(["#aad", "#556"]);

var xx = margin.top;

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

var layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer")
.style("fill", function(d, i) { return color(i); });

layer.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("y", function(d) { return y(d.x); })
.attr("x", function(d) { return x(d.y0); })
.attr("height", y.rangeBand())
.attr("width", function(d) { return x(d.y); });

var yAxis = d3.svg.axis()
.scale(y)
.tickSize(1)
.tickPadding(6)
.tickValues(labels)
.orient("left");

svg.append("g")
.attr("class", "y axis")
.call(yAxis);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.2.8/d3.min.js"></script>
<div id="container">

<section id="display" style="width: 1038px;">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:xlink="http://www.w3.org/1999/xlink" class="tributary_svg" width="677" height="533"></svg></section>
</div>

又来了,这次用的是d3 3.4.11

/*modified from Mike Bostock at http://bl.ocks.org/3943967 */

var data = [
{"key":"FL", "pop1":3000, "pop2":4000, "pop3":5000},
{"key":"CA", "pop1":3000, "pop2":3000, "pop3":3000},
{"key":"NY", "pop1":12000, "pop2":5000, "pop3":13000},
{"key":"NC", "pop1":8000, "pop2":21000, "pop3":11000},
{"key":"SC", "pop1":30000, "pop2":12000, "pop3":8000},
{"key":"AZ", "pop1":26614, "pop2":6944, "pop3":30778},
{"key":"TX", "pop1":8000, "pop2":12088, "pop3":20000}
];

var n = 3, // number of layers
m = data.length, // number of samples per layer
stack = d3.layout.stack(),
labels = data.map(function(d) {return d.key;}),

//go through each layer (pop1, pop2 etc, that's the range(n) part)
//then go through each object in data and pull out that objects's population data
//and put it into an array where x is the index and y is the number
layers = stack(d3.range(n).map(function(d) {
var a = [];
for (var i = 0; i < m; ++i) {
a[i] = {x: i, y: data[i]['pop' + (d+1)]};
}
return a;
})),

//the largest single layer
yGroupMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y; }); }),
//the largest stack
yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); });

var margin = {top: 40, right: 10, bottom: 20, left: 50},
width = 677 - margin.left - margin.right,
height = 533 - margin.top - margin.bottom;

var y = d3.scale.ordinal()
.domain(d3.range(m))
.rangeRoundBands([2, height], .08);

var x = d3.scale.linear()
.domain([0, yStackMax])
.range([0, width]);

var color = d3.scale.linear()
.domain([0, n - 1])
.range(["#aad", "#556"]);

var xx = margin.top;

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

var layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer")
.style("fill", function(d, i) { return color(i); });

layer.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("y", function(d) { return y(d.x); })
.attr("x", function(d) { return x(d.y0); })
.attr("height", y.rangeBand())
.attr("width", function(d) { return x(d.y); });

var yAxis = d3.svg.axis()
.scale(y)
.tickSize(1)
.tickPadding(6)
.tickValues(labels)
.orient("left");

svg.append("g")
.attr("class", "y axis")
.call(yAxis);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="container">

<section id="display" style="width: 1038px;">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:xlink="http://www.w3.org/1999/xlink" class="tributary_svg" width="677" height="533"></svg></section>
</div>

两个代码段的 javascript 相同,您可以清楚地看到行为不同。因此,简而言之,d3 版本处理 y 轴(尤其是附加到该轴的域)的方式有所不同。

这是一个修复了 d3 3.4.11 问题的版本

/*modified from Mike Bostock at http://bl.ocks.org/3943967 */

var data = [
{"key":"FL", "pop1":3000, "pop2":4000, "pop3":5000},
{"key":"CA", "pop1":3000, "pop2":3000, "pop3":3000},
{"key":"NY", "pop1":12000, "pop2":5000, "pop3":13000},
{"key":"NC", "pop1":8000, "pop2":21000, "pop3":11000},
{"key":"SC", "pop1":30000, "pop2":12000, "pop3":8000},
{"key":"AZ", "pop1":26614, "pop2":6944, "pop3":30778},
{"key":"TX", "pop1":8000, "pop2":12088, "pop3":20000}
];

var n = 3, // number of layers
m = data.length, // number of samples per layer
stack = d3.layout.stack(),
labels = data.map(function(d) {return d.key;}),

//go through each layer (pop1, pop2 etc, that's the range(n) part)
//then go through each object in data and pull out that objects's population data
//and put it into an array where x is the index and y is the number
layers = stack(d3.range(n).map(function(d) {
var a = [];
for (var i = 0; i < m; ++i) {
//a[i] = {x: i, y: data[i]['pop' + (d+1)]};
a[i] = {x: data[i].key, y: data[i]['pop' + (d+1)]};
}
return a;
})),

//the largest single layer
yGroupMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y; }); }),
//the largest stack
yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); });

var margin = {top: 40, right: 10, bottom: 20, left: 50},
width = 677 - margin.left - margin.right,
height = 533 - margin.top - margin.bottom;

var y = d3.scale.ordinal()
//.domain(d3.range(m))
.domain(labels)
.rangeRoundBands([2, height], .08);

var x = d3.scale.linear()
.domain([0, yStackMax])
.range([0, width]);

var color = d3.scale.linear()
.domain([0, n - 1])
.range(["#aad", "#556"]);

var xx = margin.top;

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

var layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer")
.style("fill", function(d, i) { return color(i); });

layer.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("y", function(d) { return y(d.x); })
.attr("x", function(d) { return x(d.y0); })
.attr("height", y.rangeBand())
.attr("width", function(d) { return x(d.y); });

var yAxis = d3.svg.axis()
.scale(y)
.tickSize(1)
.tickPadding(6)
//.tickValues(labels)
.orient("left");

svg.append("g")
.attr("class", "y axis")
.call(yAxis);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="container">

<section id="display" style="width: 1038px;">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:xlink="http://www.w3.org/1999/xlink" class="tributary_svg" width="677" height="533"></svg></section>
</div>

这个版本有3个不同点:

  1. 更新栈中x值的引用方式

    layers = stack(d3.range(n).map(function(d) { 
    var a = [];
    for (var i = 0; i < m; ++i) {
    //a[i] = {x: i, y: data[i]['pop' + (d+1)]};
    a[i] = {x: data[i].key, y: data[i]['pop' + (d+1)]};
    }
    return a;
    })),
  2. 更改y 比例的域

    var y = d3.scale.ordinal()
    //.domain(d3.range(m))
    .domain(labels)
    .rangeRoundBands([2, height], .08);
  3. 从 y 轴移除 .tickValues 调用。它将使用比例的

    var yAxis = d3.svg.axis()
    .scale(y)
    .tickSize(1)
    .tickPadding(6)
    //.tickValues(labels)
    .orient("left");

可以看到这个新版本在d3 3.4.11中可以正常运行。

这里是使用 d3 3.2.8 的固定版本:

/*modified from Mike Bostock at http://bl.ocks.org/3943967 */

var data = [
{"key":"FL", "pop1":3000, "pop2":4000, "pop3":5000},
{"key":"CA", "pop1":3000, "pop2":3000, "pop3":3000},
{"key":"NY", "pop1":12000, "pop2":5000, "pop3":13000},
{"key":"NC", "pop1":8000, "pop2":21000, "pop3":11000},
{"key":"SC", "pop1":30000, "pop2":12000, "pop3":8000},
{"key":"AZ", "pop1":26614, "pop2":6944, "pop3":30778},
{"key":"TX", "pop1":8000, "pop2":12088, "pop3":20000}
];

var n = 3, // number of layers
m = data.length, // number of samples per layer
stack = d3.layout.stack(),
labels = data.map(function(d) {return d.key;}),

//go through each layer (pop1, pop2 etc, that's the range(n) part)
//then go through each object in data and pull out that objects's population data
//and put it into an array where x is the index and y is the number
layers = stack(d3.range(n).map(function(d) {
var a = [];
for (var i = 0; i < m; ++i) {
//a[i] = {x: i, y: data[i]['pop' + (d+1)]};
a[i] = {x: data[i].key, y: data[i]['pop' + (d+1)]};
}
return a;
})),

//the largest single layer
yGroupMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y; }); }),
//the largest stack
yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); });

var margin = {top: 40, right: 10, bottom: 20, left: 50},
width = 677 - margin.left - margin.right,
height = 533 - margin.top - margin.bottom;

var y = d3.scale.ordinal()
//.domain(d3.range(m))
.domain(labels)
.rangeRoundBands([2, height], .08);

var x = d3.scale.linear()
.domain([0, yStackMax])
.range([0, width]);

var color = d3.scale.linear()
.domain([0, n - 1])
.range(["#aad", "#556"]);

var xx = margin.top;

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

var layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer")
.style("fill", function(d, i) { return color(i); });

layer.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("y", function(d) { return y(d.x); })
.attr("x", function(d) { return x(d.y0); })
.attr("height", y.rangeBand())
.attr("width", function(d) { return x(d.y); });

var yAxis = d3.svg.axis()
.scale(y)
.tickSize(1)
.tickPadding(6)
//.tickValues(labels)
.orient("left");

svg.append("g")
.attr("class", "y axis")
.call(yAxis);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.2.8/d3.min.js"></script>
<div id="container">

<section id="display" style="width: 1038px;">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:xlink="http://www.w3.org/1999/xlink" class="tributary_svg" width="677" height="533"></svg></section>
</div>

它似乎在 d3 3.2.8 中也能正常工作,所以它应该可以解决您的问题。

这是一个有趣的诊断,我唯一能想到的是 tributary.io 基于 d3 的旧版本,其中轴/域交互工作正常(尽管已损坏)并且在您的独立版本中,您引用的是最新版本,它解决了所有问题(导致可视化损坏,因为您的代码依赖于它)。

注意:弄清楚这个很有趣,但我在 26029141 的回答中没有附加评论几乎不可能诊断出来。

关于javascript - d3.js 如何从数组中绘制堆叠的水平条?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28491838/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com