javascript - d3.js 堆积面积图 - 不出现
问题描述
我正在构建一个堆叠区域图(按照本教程)并且在图形渲染方面遇到问题。轴正确渲染,但区域元素未出现。当只使用一列数据时,它可以正常工作,但是在堆叠数据之后,就没有运气了。
我觉得问题出在我使用scaleLinear()
.
我尝试了两种方法:将y
值从d3.stack
我得到负值的函数中取出(在下面的代码中注释)。其次,为了调试,我将最大值设置为最大值stackedData
(在下面的代码中设置为默认值)。当我使用 时,这会给出所有正值console.log
,但没有图形呈现。
这是代码:
var margin = {top: 10, right: 30, bottom: 30, left: 70},
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var svg = d3.select("#chart")
.append("svg")
.attr("width",width + margin.left + margin.right)
.attr("height",height + margin.top + margin.bottom)
.append("g")
.attr("transform","translate("+margin.left+","+margin.top+")");
let data = []
var group_names = []
//Assumes first line of data is table header, otherwise will not work properly
model.output_energy_demand.map(function(x,i){
if(i==0) {
group_names = x
}else{
let line = {}
x.map(function(y,j){
line[group_names[j]]=y
});
data.push(line)
}
});
data.forEach((d,i)=>{
var keys = Object.keys(d)
console.log(model.year[i])
d["year"] = d3.timeParse("%Y")(model.year[i])
for(var j=0;j<keys.length;j++){
d[keys[i]] = +d[keys[j]]
}
});
if(typeof(data)!="undefined") {
console.log("Data loaded")
console.log(model.year)
//Stacking data
var sumstat = d3.nest()
.key(function(d) { return d.year;})
.entries(data);
var stackedData = d3.stack()
.keys(group_names)
.value(function(d,key){
return d.values[0][key]
})(sumstat);
//Set up axes
var x = d3.scaleTime()
.domain(d3.extent(model.year.map((d,i)=>{return d3.timeParse("%Y")(d)})))
.range([0,width]);
svg.append("g")
.attr("transform","translate(0,"+height+")")
.call(d3.axisBottom(x));
svg.append("text")
.attr("x",width*.5)
.attr("y",height+margin.bottom)
.style("text-anchor","middle")
.attr("font-family","Tahoma")
.text("Year")
var y = d3.scaleLinear()
// Finds maximum of stackedData, which avoids negative values (but gives incorrect values on the y-axis)
.domain([0,d3.max(stackedData,
function(d){
//Find maximum value of data
var max = 0;
d.forEach(function(e,i){
console.log(e);
if(d3.max(e)>max) max=d3.max(e)
})
return max
})
])
// Finds maximum of stackedData, which gives correct values on the y-axis, but causes negative values to come out of y(d[0])
// .domain([0,d3.max(data,
// function(d){
// //Find maximum value of data
// var max = 0;
// group_names.forEach(function(key,i){
// console.log(key);
// if(d[key]>max) max=d[key]
// })
// return max
// })
// ])
.range([ height,0])
svg.append("g")
.call(d3.axisLeft(y));
svg.append("text")
.attr("y",-margin.left)
.attr("x",-height*.5)
.attr("dy","1em")
.style("text-anchor","middle")
.attr("font-family","Tahoma")
.attr("transform","rotate(-90)")
.text("Energy Demand (TWh /year)")
console.log("About to plot data ")
svg
.selectAll("layers")
.data(stackedData)
.enter()
.append("path")
.attr("fill",function(d){return color()})
.attr("d", d3.area()
.x(function(d,i){ console.log("Data on line", d.data); return x(d3.timeParse("%Y")(d.data.key)) })
.y0(function(d) {console.log(d[0] +"-> y0: "+y(d[0])); return y(d[0])})
.y1(function(d){ console.log(d[1] + "-> y1: "+y(d[1])); return y(d[1])})
)
}else{
d3.select("#chart").append("Error loading data")
}
这是 的结构data
:
(33) […]
0: {…}
"Electricity by CSP": 0
"Electricity by PV": 0
"Electricity by geothermal": 0
"Electricity by hydropower": 300.89983280022
"Electricity by marine power": 0
"Electricity by offshore wind": 0
"Electricity by onshore wind": 0
"Renewable energy": 258.219863514757
"Solid bioenergy": 254.640155086192
"Total demand for coal": 3711.42425220673
"Total demand for crude oil": 7523.960117178
"Total demand for natural gas": 254.640155086192
"Total demand for nuclear fuel": 2449.95477156234
year: Date Mon Jan 01 1990 00:00:00 GMT+0000 (Greenwich Mean Time)
<prototype>: Object { … }
1: Object { "Total demand for natural gas": 3220.14298481777, "Total demand for crude oil": 277.599399485849, "Total demand for coal": 3662.11547993736, … }
2: Object { "Total demand for natural gas": 3200.81379949803, "Total demand for crude oil": 7756.9933670896, "Total demand for coal": 273.508068071529, … }
...
有任何想法吗?
编辑:2020-02-21 我在这里发布了一个实时版本:https ://jsfiddle.net/turium/ywrbkzm9/
解决方案
我检查了你的代码,有几个错误。我已将它们替换为正确的,您可以在此基础上进行研发。
- 没有从您附加路径的位置调用颜色函数。
- 有不必要的数据嵌套。
- 创建了一个空模型对象,所以 jsfiddle 给出了一个错误
- 删除了时间尺度,因为它增加了开销
用不带逗号的年份显示 x 轴的代码。
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickFormat(function(d) {
return d;
}));
model = {}
model.year = [
1990,
1991,
1992,
1993,
1994,
1995,
1996,
1997,
1998,
1999,
2000,
2001,
2002,
2003,
2004,
2005,
2006,
2007,
2008,
2009,
2010,
2011,
2012,
2013,
2014,
2015,
2020,
2025,
2030,
2035,
2040,
2045,
2050
]
model.output_energy_demand = [
[
"Total demand for natural gas",
"Total demand for crude oil",
"Total demand for coal",
"Electricity by geothermal",
"Electricity by hydropower",
"Electricity by marine power",
"Electricity by CSP",
"Electricity by PV",
"Electricity by offshore wind",
"Electricity by onshore wind",
"Total demand for nuclear fuel",
"Renewable energy",
"Solid bioenergy"
],
[
3102.40524991691,
7523.960117178,
3711.42425220673,
0,
300.89983280022,
0,
0,
0,
0,
0,
2449.95477156234,
258.219863514757,
254.640155086192
],
[
3220.14298481777,
7805.34286934201,
3662.11547993736,
0,
314.08215981732,
0,
0,
0,
0,
0,
2392.85347025885,
281.174663414415,
277.599399485849
],
[
3200.81379949803,
7756.9933670896,
3445.10585509343,
0,
340.4890868346,
0,
0,
0,
0,
0,
2512.86260946551,
277.266526000094,
273.508068071529
],
[
3305.31292778359,
7783.82326263428,
3472.68950574908,
0,
353.62925132022,
0,
0,
0,
0,
0,
2666.91820506714,
305.773519651316,
302.045477722751
],
[
3367.00236478057,
7565.09225038114,
3413.93067723008,
0,
367.522212360599,
0,
0,
0,
0,
0,
2657.48508853596,
292.303360572476,
288.50963564391
],
[
3487.48732706185,
7615.43451245472,
3406.94135763491,
0,
362.74326344874,
0,
0,
0,
0,
0,
2720.41544041992,
297.511985344959,
293.709384916393
],
[
3744.9593399799,
7826.17851688842,
3449.136453147,
0,
355.3673026203,
0,
0,
0,
0,
0,
2871.17913811302,
323.48891655571,
319.711924627145
],
[
3734.32219482531,
7545.58234604822,
3285.22078771847,
0,
367.27291222956,
0,
0,
0,
0,
0,
2895.07611993084,
333.778821035599,
329.987640607034
],
[
3834.40132308377,
7645.80240057448,
3258.37777947803,
0,
377.0867016027,
0,
0,
0,
0,
0,
2889.95225758379,
334.216219338001,
330.408223409436
],
[
3934.10235529276,
7393.72102051037,
3147.43143379234,
0,
383.18690200752,
0,
0,
0,
0,
0,
2914.35741090846,
327.381123667362,
323.534358238797
],
[
4087.04502061623,
7247.4110570115,
3353.99479917852,
4.82547708666,
393.52232123964,
0.5071937472,
0,
0.203524605,
0,
26.81745703056,
2931.59347644636,
332.014849186351,
326.489968757786
],
[
4187.85080191466,
7646.26147968543,
3384.51199334096,
4.64857517429999,
420.262811562959,
0.4852086192,
0,
0.30943918638,
0,
33.45917086152,
3022.71240680316,
336.487547234091,
330.881864107789
],
[
4205.18925700953,
7579.67080593577,
3385.97805263338,
4.79569679315999,
353.99917660788,
0.494507592,
0,
0.4051566306,
0,
46.3006537083,
3067.10289195713,
337.738844971462,
332.131957416555
],
[
4428.70123473367,
7834.71813308874,
3524.45624865725,
5.4612635832,
343.52520531084,
0.4898581056,
0,
0.72565105788,
0,
50.9478361405199,
3069.27182555567,
374.37075694017,
368.147127662413
],
[
4551.82743034029,
8009.62808231553,
3449.96219341097,
5.564770758,
362.514048853499,
0.470082009599999,
0,
1.46273236614,
0,
67.69761449058,
3119.33911585662,
366.098265091526,
359.153478032005
],
[
4604.74358239693,
8096.18416223813,
3381.05306785008,
5.44094040114,
344.3848462566,
0.4813375536,
0,
2.64236395716,
0,
78.3154704733199,
3066.35144843448,
386.969328558568,
379.391483494566
],
[
4560.10999341729,
8203.04705336058,
3469.86003803626,
5.61711543678,
346.81026188232,
0.4642543728,
0,
3.73148887734,
0,
91.38316529736,
3050.45111617217,
394.148276719482,
385.458486662152
],
[
4519.7188056018,
7948.7483718475,
3463.98671155763,
5.82834632004,
349.48220898564,
0.4654325232,
0.00484251372,
6.14455873164,
0,
118.81064914452,
2896.72897237308,
411.77345085889,
401.790597859782
],
[
4642.45980752563,
8095.41788904162,
3208.68777524172,
5.78038393997999,
368.10858903516,
0.4654325232,
0.0094111776,
12.7615925908799,
2.60895690648,
132.13721227626,
2918.12383597752,
446.017117805582,
433.655553095456
],
[
4300.19124830045,
7719.81278137145,
2876.38739207936,
5.58780088086,
371.310269112539,
0.44894025846,
0.11373727212,
20.3917959088199,
5.744841114762,
145.29539623914,
2921.42403037908,
467.905545984921,
453.394070650256
],
[
4692.03986900568,
7797.53751476991,
2959.25747160129,
5.6382101145,
412.797954991499,
0.477972636839999,
0.8062598628,
35.0866669474799,
8.22484405134,
157.81866688674,
2856.24810989478,
498.364549610955,
481.466736916603
],
[
4235.58374324098,
7538.66495957225,
3005.00134812211,
5.91160946975999,
344.426769476279,
0.478098341279999,
1.3839112116,
66.1100621738399,
11.72086686054,
179.46124283664,
2799.25195982939,
442.390139292031,
425.641578089282
],
[
4107.70809841702,
7399.30695265121,
3137.64857648784,
5.80847765508,
374.23402394886,
0.46268411922,
3.98578825818,
86.04398912724,
16.05857548068,
204.94524478734,
2736.84193438788,
495.32616138678,
475.76987559724
],
[
4043.0896536257,
7415.72476474021,
3039.06605229034,
5.97630596849999,
409.64636857176,
0.420999422399999,
5.21086402044,
94.70094727536,
21.5588025313199,
227.79819933624,
2708.12027152385,
505.670520272608,
483.316979888301
],
[
3598.13284429141,
7317.86276802473,
2846.1651910181,
6.26113715202,
412.580152851659,
0.48353974812,
5.89504961916,
102.0072482082,
25.42716943056,
240.05775513006,
2711.96611313418,
454.88706631646,
432.892324258519
],
[
3754.93540354624,
7511.65923877049,
2800.70818111911,
6.6793685346,
380.261269231019,
0.495524623319999,
6.07585064832,
114.06062251008,
39.85985729862,
276.41099985318,
2645.38509787332,
495.328376085096,
465.28909250104
],
[
4043.59078735007,
8017.18489716505,
2338.95806864845,
6.7875256341,
394.603505735554,
0.51747170688,
6.07585064832,
145.892562054913,
83.1198330814429,
408.732059173849,
2480.44614477944,
427.441506546882,
409.905742992792
],
[
3291.51973731274,
4997.05071692697,
452.188235416201,
63.9709506160571,
446.050495741098,
11.6326046301965,
85.869709014152,
220.181406509467,
609.256812048776,
529.707140310043,
2717.66461431481,
593.564950874224,
388.443809434111
],
[
2885.96717926539,
2676.62515437839,
293.191002866746,
121.154375598014,
498.701133634033,
22.747737553513,
165.663567379984,
293.862964912845,
1131.43400447885,
649.689673274539,
2893.87542604889,
676.605125561303,
339.139457453926
],
[
2664.88017244303,
1096.4584151475,
233.59485578412,
178.337800579971,
543.439537600747,
33.8628704768296,
245.457425745816,
367.884313156941,
1650.85948123489,
769.503145366082,
2732.03449314671,
636.789912347858,
258.105935984877
],
[
2546.12143825256,
383.69776070687,
144.591148980276,
235.521225561928,
587.785639945705,
44.9780034001461,
325.251284111648,
441.672179518208,
2167.12983644434,
889.008654837177,
2379.90569231828,
511.758583755248,
174.052538556381
],
[
2597.56379334278,
275.045700399492,
98.1839204037293,
292.704650543886,
631.738388993547,
56.0931363234626,
405.04514247748,
515.225029663832,
2680.25396805022,
1007.80883971052,
1913.52680335554,
530.552643420933,
153.689961713093
],
[
2749.62249643278,
192.082054109743,
61.7232837841147,
349.888075525843,
681.054211190302,
67.2082692467792,
484.839000843312,
587.790589413631,
3189.00909148252,
1125.32442426428,
1779.67241790878,
550.847796398766,
135.833335875956
]
]
//Draw graph
var margin = {
top: 10,
right: 30,
bottom: 30,
left: 70
},
width = 960 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var svg = d3.select("#chart")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
let data = []
var group_names = []
//Assumes first line of data is table header, otherwise will not work properly
debugger;
model.output_energy_demand.map(function(x, i) {
if (i == 0) {
group_names = x
} else {
let line = {}
x.map(function(y, j) {
line[group_names[j]] = y
});
data.push(line)
}
});
/* data.forEach((d, i) => {
var keys = Object.keys(d)
d.year = model.year[i];
for (var j = 0; j < keys.length; j++) {
d[keys[i]] = +d[keys[j]]
}
}); */
data.forEach((d, i) => {
d['year'] = model.year[i];
});
if (typeof(data) != "undefined") {
var stackedData = d3.stack()
.keys(group_names)
(data);
debugger;
//Set up axes
var x = d3.scaleLinear()
.domain(d3.extent(model.year.map((d, i) => {
return d
})))
.range([0, width])
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickFormat(function(d) {
return d;
}));
svg.append("text")
.attr("x", width * 0.5)
.attr("y", height + margin.bottom)
.style("text-anchor", "middle")
.attr("font-family", "Tahoma")
.text("Year")
var y = d3.scaleLinear()
.domain([0, d3.max(stackedData,
function(d) {
//Find maximum value of data
var max = 0;
d.forEach(function(e, i) {
if (d3.max(e) > max) max = d3.max(e)
})
return max
})])
.range([height, 0])
svg.append("g")
.call(d3.axisLeft(y));
svg.append("text")
.attr("y", -margin.left)
.attr("x", -height * 0.5)
.attr("dy", "1em")
.style("text-anchor", "middle")
.attr("font-family", "Tahoma")
.attr("transform", "rotate(-90)")
.text("Energy Demand (TWh /year)")
svg
.selectAll("layers")
.data(stackedData)
.enter()
.append("path")
.style("fill", function(d) {
var n = Math.random() * (16 ** 7 - 1)
let val = (n.toString(16)).slice(0, 6)
return `#${val}`;
})
.attr("d", d3.area()
.x(function(d, i) {
return x(d.data.year)
})
.y0(function(d) {
return y(d[0])
})
.y1(function(d) {
return y(d[1])
})
)
} else {
d3.select("#chart").append("Error loading data")
}
body {
border: 0;
margin: 0;
min-height: 100%;
width: 100%;
}
h2 {
font-family: sans-serif;
font-weight: bold;
font-size: 28px;
}
#header {
height: 56px;
position: relative;
top: 0;
left: 0;
width: 100%;
background-color: #666666;
}
#header div {
padding: 5px 0 0 10px;
}
#header span {
color: #ffffff;
font-family: sans-serif;
font-weight: bold;
font-size: 36px;
text-shadow: #000000 1px
}
#content {
margin: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.3.0/d3.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<!--<link href="css/index.css" rel="stylesheet"/>-->
<title>Stacked Area Chart</title>
</head>
<body>
<div id="header">
<div>
<span>Stacked Area Chart</span>
</div>
</div>
<div id="content">
<h2>Demo 1: Basic Graph</h2>
<div id="chart"></div>
</div>
<!--<script type="text/javascript" src="javascripts/stacked_graph1.js"></script>-->
</body>
</html>
下面的代码弄乱了数据,因此用更简单的代码替换它以向数据集添加年份。
// Commented below code as it was distorting current dataset
/* data.forEach((d, i) => {
var keys = Object.keys(d)
d.year = model.year[i];
for (var j = 0; j < keys.length; j++) {
d[keys[i]] = +d[keys[j]
}
}); */
// Use below code.
data.forEach((d, i) => {
d['year'] = model.year[i];
});
推荐阅读
- java - 是否可以在 Akka 演员内部设置不使用事件的计时器?(输入阿卡)
- angular - Angular on refresh getItem undefined for Local storage service
- delphi - 如何在所有者绘制的 ListView 中恢复突出显示功能
- ruby-on-rails - 仅在其所有 has_many 集合都具有特定列的值时查找对象
- android - 颤振错误:每个孩子必须恰好布置一次。点击手势检测器
- angular - 目标入口点“@angular/cdk/platform”缺少依赖项
- c++ - 将结构复制到具有 const 值的数组
- google-cloud-platform - 如何在 GCP 中创建 Windows VM,以便我们可以在 Jenkins 中使用它进行自动化测试
- c++ - 队列交换 C++ STL
- r - R ggplot2:geom_area按组获取线型