D3.js v5 - 不渲染的简单流图
D3.js v5 - simple streamgraph not rendering
在下面的代码片段中,我有一个使用硬编码数据和最少样式的极其简化的流图。
var margin = {top: 20, right: 30, bottom: 0, left: 10},
width = 900 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom;
var svg = d3.select("body")
.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 + ")");
var data = [{'active': 56733306054.0,
'bond': 3525783856.0,
'date': 'Apr-15',
'mmf': 1403672993.0,
'other': 0.0,
'passive': 6821599781.0},
{'active': 5716791269.0,
'bond': 6085973929.0,
'date': 'Jul-15',
'mmf': 3941955156.0,
'other': 0.0,
'passive': 669757365.2},
{'active': 17062997217.0,
'bond': 4039598099.0,
'date': 'Oct-15',
'mmf': 4009017950.0,
'other': 0.0,
'passive': 726136994.3},
{'active': 7814464858.0,
'bond': 4262416085.0,
'date': 'Jan-16',
'mmf': 6942848526.0,
'other': 1868408693.0,
'passive': 576693480.6},
{'active': 3225887820.0,
'bond': 1997520654.0,
'date': 'Apr-16',
'mmf': 8803909471.0,
'other': 1829867764.0,
'passive': 658579093.5},
{'active': 7552865110.0,
'bond': 2774538610.0,
'date': 'Jul-16',
'mmf': 17168667665.0,
'other': 1781624412.0,
'passive': 1062492998.0},
{'active': 9921160101.0,
'bond': 4749422921.0,
'date': 'Oct-16',
'mmf': 19897031580.0,
'other': 1642076470.0,
'passive': 1001209305.0},
{'active': 11432914047.0,
'bond': 6282916561.0,
'date': 'Jan-17',
'mmf': 10962414198.0,
'other': 1540325097.0,
'passive': 1865670585.0},
{'active': 12239976192.0,
'bond': 5161108076.0,
'date': 'Apr-17',
'mmf': 7858159818.0,
'other': 1423157123.0,
'passive': 1394368561.0},
{'active': 12538521595.0,
'bond': 4844007015.0,
'date': 'Jul-17',
'mmf': 10153574680.0,
'other': 1327231248.0,
'passive': 982569223.9},
{'active': 13660436312.0,
'bond': 4831471993.0,
'date': 'Oct-17',
'mmf': 9105515290.0,
'other': 1226448389.0,
'passive': 660421454.6},
{'active': 18238784924.0,
'bond': 6926050754.0,
'date': 'Jan-18',
'mmf': 8997606297.0,
'other': 0.0,
'passive': 502423215.8},
{'active': 16515400278.0,
'bond': 8174797500.0,
'date': 'Apr-18',
'mmf': 10488139471.0,
'other': 0.0,
'passive': 641632439.9},
{'active': 14469020809.0,
'bond': 10154350717.0,
'date': 'Jul-18',
'mmf': 12795032278.0,
'other': 0.0,
'passive': 373254191.0},
{'active': 11941160301.0,
'bond': 11565983214.0,
'date': 'Oct-18',
'mmf': 9868174645.0,
'other': 0.0,
'passive': 500573365.9},
{'active': 13065033332.0,
'bond': 13150111094.0,
'date': 'Jan-19',
'mmf': 9383725064.0,
'other': 0.0,
'passive': 348729651.5},
{'active': 13015515107.0,
'bond': 13530625221.0,
'date': 'Apr-19',
'mmf': 10134077571.0,
'other': 0.0,
'passive': 289549779.9},
{'active': 15803115946.0,
'bond': 16503245488.0,
'date': 'Jul-19',
'mmf': 10938147334.0,
'other': 0.0,
'passive': 364098177.7},
{'active': 19281878473.0,
'bond': 22592356870.0,
'date': 'Oct-19',
'mmf': 13042415142.0,
'other': 0.0,
'passive': 1182250058.0},
{'active': 26486960563.0,
'bond': 26446208720.0,
'date': 'Jan-20',
'mmf': 14980167197.0,
'other': 0.0,
'passive': 825650931.1},
{'active': 26551390384.0,
'bond': 27921669739.0,
'date': 'Apr-20',
'mmf': 9558841841.0,
'other': 0.0,
'passive': 841110171.1},
{'active': 26498733168.0,
'bond': 23387500164.0,
'date': 'Jul-20',
'mmf': 9754774244.0,
'other': 0.0,
'passive': 930687399.1},
{'active': 30362195233.0,
'bond': 25104023352.0,
'date': 'Oct-20',
'mmf': 14576442586.0,
'other': 0.0,
'passive': 981491044.5},
{'active': 33018698783.0,
'bond': 19038462941.0,
'date': 'Jan-21',
'mmf': 15537675080.0,
'other': 0.0,
'passive': 875201720.9},
{'active': 50881100695.0,
'bond': 15108333888.0,
'date': 'Apr-21',
'mmf': 17027529982.0,
'other': 0.0,
'passive': 781991391.3}];
var keys = ['date','bond','active','passive','mmf','other'];
var x = d3.scaleTime()
.domain([new Date('01/01/2014'), new Date('01/01/2022')])
.range([ 0, width ]);
svg.append("g")
.attr("transform", "translate(0," + height*0.8 + ")")
.call(d3.axisBottom(x).tickSize(-height*.7).tickValues([new Date("01/01/2014"),new Date('01/01/2018')]))
.select(".domain").remove()
svg.selectAll(".tick line").attr("stroke", "#b8b8b8")
var y = d3.scaleLinear()
.domain([0, 1000000000])
.range([ height, 0 ]);
var stackedData = d3.stack()
.offset(d3.stackOffsetSilhouette)
.keys(keys)
(data)
var area = d3.area()
.x(function(d) { return x(new Date(d.data.date)); })
.y0(function(d) { return y(d[0]); })
.y1(function(d) { return y(d[1]); });
svg
.selectAll("mylayers")
.data(stackedData)
.enter()
.append("path")
.attr("class", "myArea")
.style("fill", "#003366")
.attr("d", area);
<script src="https://d3js.org/d3.v5.min.js"></script>
正如我们所见,图表未显示,但同时未标记任何错误。
问题
鉴于代码的简单性和与看到的功能齐全的模板的相似性 here,为什么此图无法按预期呈现?
我认为您需要将日期转换为数值,这样的一些代码可能会有所帮助
var dateParser = d3.timeParse('%b-%y')
var area = d3.area()
.x(function(d) { return x(dateParser(d.data.date)); })
.y0(function(d) { return y(d[0]); })
.y1(function(d) { return y(d[1]); });
这是一个工作示例:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<script>
const margin = { top: 20, right: 20, bottom: 20, left: 20 },
width = 900 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom;
const svg = d3.select("body")
.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})`);
const parseDate = d3.timeParse('%b-%y');
var data = [{
'active': 56733306054.0,
'bond': 3525783856.0,
'date': 'Apr-15',
'mmf': 1403672993.0,
'other': 0.0,
'passive': 6821599781.0
},
{
'active': 5716791269.0,
'bond': 6085973929.0,
'date': 'Jul-15',
'mmf': 3941955156.0,
'other': 0.0,
'passive': 669757365.2
},
{
'active': 17062997217.0,
'bond': 4039598099.0,
'date': 'Oct-15',
'mmf': 4009017950.0,
'other': 0.0,
'passive': 726136994.3
},
{
'active': 7814464858.0,
'bond': 4262416085.0,
'date': 'Jan-16',
'mmf': 6942848526.0,
'other': 1868408693.0,
'passive': 576693480.6
},
{
'active': 3225887820.0,
'bond': 1997520654.0,
'date': 'Apr-16',
'mmf': 8803909471.0,
'other': 1829867764.0,
'passive': 658579093.5
},
{
'active': 7552865110.0,
'bond': 2774538610.0,
'date': 'Jul-16',
'mmf': 17168667665.0,
'other': 1781624412.0,
'passive': 1062492998.0
},
{
'active': 9921160101.0,
'bond': 4749422921.0,
'date': 'Oct-16',
'mmf': 19897031580.0,
'other': 1642076470.0,
'passive': 1001209305.0
},
{
'active': 11432914047.0,
'bond': 6282916561.0,
'date': 'Jan-17',
'mmf': 10962414198.0,
'other': 1540325097.0,
'passive': 1865670585.0
},
{
'active': 12239976192.0,
'bond': 5161108076.0,
'date': 'Apr-17',
'mmf': 7858159818.0,
'other': 1423157123.0,
'passive': 1394368561.0
},
{
'active': 12538521595.0,
'bond': 4844007015.0,
'date': 'Jul-17',
'mmf': 10153574680.0,
'other': 1327231248.0,
'passive': 982569223.9
},
{
'active': 13660436312.0,
'bond': 4831471993.0,
'date': 'Oct-17',
'mmf': 9105515290.0,
'other': 1226448389.0,
'passive': 660421454.6
},
{
'active': 18238784924.0,
'bond': 6926050754.0,
'date': 'Jan-18',
'mmf': 8997606297.0,
'other': 0.0,
'passive': 502423215.8
},
{
'active': 16515400278.0,
'bond': 8174797500.0,
'date': 'Apr-18',
'mmf': 10488139471.0,
'other': 0.0,
'passive': 641632439.9
},
{
'active': 14469020809.0,
'bond': 10154350717.0,
'date': 'Jul-18',
'mmf': 12795032278.0,
'other': 0.0,
'passive': 373254191.0
},
{
'active': 11941160301.0,
'bond': 11565983214.0,
'date': 'Oct-18',
'mmf': 9868174645.0,
'other': 0.0,
'passive': 500573365.9
},
{
'active': 13065033332.0,
'bond': 13150111094.0,
'date': 'Jan-19',
'mmf': 9383725064.0,
'other': 0.0,
'passive': 348729651.5
},
{
'active': 13015515107.0,
'bond': 13530625221.0,
'date': 'Apr-19',
'mmf': 10134077571.0,
'other': 0.0,
'passive': 289549779.9
},
{
'active': 15803115946.0,
'bond': 16503245488.0,
'date': 'Jul-19',
'mmf': 10938147334.0,
'other': 0.0,
'passive': 364098177.7
},
{
'active': 19281878473.0,
'bond': 22592356870.0,
'date': 'Oct-19',
'mmf': 13042415142.0,
'other': 0.0,
'passive': 1182250058.0
},
{
'active': 26486960563.0,
'bond': 26446208720.0,
'date': 'Jan-20',
'mmf': 14980167197.0,
'other': 0.0,
'passive': 825650931.1
},
{
'active': 26551390384.0,
'bond': 27921669739.0,
'date': 'Apr-20',
'mmf': 9558841841.0,
'other': 0.0,
'passive': 841110171.1
},
{
'active': 26498733168.0,
'bond': 23387500164.0,
'date': 'Jul-20',
'mmf': 9754774244.0,
'other': 0.0,
'passive': 930687399.1
},
{
'active': 30362195233.0,
'bond': 25104023352.0,
'date': 'Oct-20',
'mmf': 14576442586.0,
'other': 0.0,
'passive': 981491044.5
},
{
'active': 33018698783.0,
'bond': 19038462941.0,
'date': 'Jan-21',
'mmf': 15537675080.0,
'other': 0.0,
'passive': 875201720.9
},
{
'active': 50881100695.0,
'bond': 15108333888.0,
'date': 'Apr-21',
'mmf': 17027529982.0,
'other': 0.0,
'passive': 781991391.3
}].map(d => {
d['date'] = parseDate(d['date']);
return d;
});
const keys = ['bond', 'active', 'passive', 'mmf', 'other'];
const x = d3.scaleTime()
.domain(d3.extent(data, d => d.date))
.range([0, width]);
svg.append("g")
.attr("transform", `translate(0,${height})`)
.call(
d3.axisBottom(x)
.tickSize(-height)
)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").attr("stroke", "#b8b8b8"));
/*
code from https://observablehq.com/@d3/streamgraph
The d3-shape docs say that d3.stackOffsetWiggle "Shifts the baseline
so as to minimize the weighted wiggle of layers. This offset is recommended
for streamgraphs in conjunction with the inside-out order."
*/
const stackedData = d3.stack()
.order(d3.stackOrderInsideOut)
.offset(d3.stackOffsetWiggle)
.keys(keys)
(data);
// the domain of the y-scale should cover the min and max of the stacked data
// code from https://observablehq.com/@d3/streamgraph
const y = d3.scaleLinear()
.domain([
d3.min(stackedData, d => d3.min(d, d => d[0])),
d3.max(stackedData, d => d3.max(d, d => d[1]))
])
.range([height, 0]);
const color = d3.scaleOrdinal()
.domain(keys)
.range(d3.schemeCategory10);
const area = d3.area()
.x(d => x(d.data.date))
.y0(d => y(d[0]))
.y1(d => y(d[1]));
svg.append('g')
.selectAll("path")
.data(stackedData)
.join("path")
.style("fill", d => color(d.key))
.attr("d", area);
</script>
</body>
正如 James 的回答所说,您应该使用 d3.timeParse
将字符串转换为日期,而不是依赖 Date()
构造函数,即 unreliable。此外,您的 keys
数组应仅包含堆叠的属性,因此不应包含“日期”。
我为 d3.stackOffsetWiggle
引用了 Mike Bostock's streamgraph example for the stack generator and the y-scale. The d3-shape docs 说它“移动基线以最小化图层的加权摆动。建议将此偏移量与由内而外的顺序一起用于流图。 “我遵循该建议而不是使用 d3.stackOffsetSilhouette
。最后,按照示例,y 尺度的域应覆盖堆叠数据的最小值和最大值。
在下面的代码片段中,我有一个使用硬编码数据和最少样式的极其简化的流图。
var margin = {top: 20, right: 30, bottom: 0, left: 10},
width = 900 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom;
var svg = d3.select("body")
.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 + ")");
var data = [{'active': 56733306054.0,
'bond': 3525783856.0,
'date': 'Apr-15',
'mmf': 1403672993.0,
'other': 0.0,
'passive': 6821599781.0},
{'active': 5716791269.0,
'bond': 6085973929.0,
'date': 'Jul-15',
'mmf': 3941955156.0,
'other': 0.0,
'passive': 669757365.2},
{'active': 17062997217.0,
'bond': 4039598099.0,
'date': 'Oct-15',
'mmf': 4009017950.0,
'other': 0.0,
'passive': 726136994.3},
{'active': 7814464858.0,
'bond': 4262416085.0,
'date': 'Jan-16',
'mmf': 6942848526.0,
'other': 1868408693.0,
'passive': 576693480.6},
{'active': 3225887820.0,
'bond': 1997520654.0,
'date': 'Apr-16',
'mmf': 8803909471.0,
'other': 1829867764.0,
'passive': 658579093.5},
{'active': 7552865110.0,
'bond': 2774538610.0,
'date': 'Jul-16',
'mmf': 17168667665.0,
'other': 1781624412.0,
'passive': 1062492998.0},
{'active': 9921160101.0,
'bond': 4749422921.0,
'date': 'Oct-16',
'mmf': 19897031580.0,
'other': 1642076470.0,
'passive': 1001209305.0},
{'active': 11432914047.0,
'bond': 6282916561.0,
'date': 'Jan-17',
'mmf': 10962414198.0,
'other': 1540325097.0,
'passive': 1865670585.0},
{'active': 12239976192.0,
'bond': 5161108076.0,
'date': 'Apr-17',
'mmf': 7858159818.0,
'other': 1423157123.0,
'passive': 1394368561.0},
{'active': 12538521595.0,
'bond': 4844007015.0,
'date': 'Jul-17',
'mmf': 10153574680.0,
'other': 1327231248.0,
'passive': 982569223.9},
{'active': 13660436312.0,
'bond': 4831471993.0,
'date': 'Oct-17',
'mmf': 9105515290.0,
'other': 1226448389.0,
'passive': 660421454.6},
{'active': 18238784924.0,
'bond': 6926050754.0,
'date': 'Jan-18',
'mmf': 8997606297.0,
'other': 0.0,
'passive': 502423215.8},
{'active': 16515400278.0,
'bond': 8174797500.0,
'date': 'Apr-18',
'mmf': 10488139471.0,
'other': 0.0,
'passive': 641632439.9},
{'active': 14469020809.0,
'bond': 10154350717.0,
'date': 'Jul-18',
'mmf': 12795032278.0,
'other': 0.0,
'passive': 373254191.0},
{'active': 11941160301.0,
'bond': 11565983214.0,
'date': 'Oct-18',
'mmf': 9868174645.0,
'other': 0.0,
'passive': 500573365.9},
{'active': 13065033332.0,
'bond': 13150111094.0,
'date': 'Jan-19',
'mmf': 9383725064.0,
'other': 0.0,
'passive': 348729651.5},
{'active': 13015515107.0,
'bond': 13530625221.0,
'date': 'Apr-19',
'mmf': 10134077571.0,
'other': 0.0,
'passive': 289549779.9},
{'active': 15803115946.0,
'bond': 16503245488.0,
'date': 'Jul-19',
'mmf': 10938147334.0,
'other': 0.0,
'passive': 364098177.7},
{'active': 19281878473.0,
'bond': 22592356870.0,
'date': 'Oct-19',
'mmf': 13042415142.0,
'other': 0.0,
'passive': 1182250058.0},
{'active': 26486960563.0,
'bond': 26446208720.0,
'date': 'Jan-20',
'mmf': 14980167197.0,
'other': 0.0,
'passive': 825650931.1},
{'active': 26551390384.0,
'bond': 27921669739.0,
'date': 'Apr-20',
'mmf': 9558841841.0,
'other': 0.0,
'passive': 841110171.1},
{'active': 26498733168.0,
'bond': 23387500164.0,
'date': 'Jul-20',
'mmf': 9754774244.0,
'other': 0.0,
'passive': 930687399.1},
{'active': 30362195233.0,
'bond': 25104023352.0,
'date': 'Oct-20',
'mmf': 14576442586.0,
'other': 0.0,
'passive': 981491044.5},
{'active': 33018698783.0,
'bond': 19038462941.0,
'date': 'Jan-21',
'mmf': 15537675080.0,
'other': 0.0,
'passive': 875201720.9},
{'active': 50881100695.0,
'bond': 15108333888.0,
'date': 'Apr-21',
'mmf': 17027529982.0,
'other': 0.0,
'passive': 781991391.3}];
var keys = ['date','bond','active','passive','mmf','other'];
var x = d3.scaleTime()
.domain([new Date('01/01/2014'), new Date('01/01/2022')])
.range([ 0, width ]);
svg.append("g")
.attr("transform", "translate(0," + height*0.8 + ")")
.call(d3.axisBottom(x).tickSize(-height*.7).tickValues([new Date("01/01/2014"),new Date('01/01/2018')]))
.select(".domain").remove()
svg.selectAll(".tick line").attr("stroke", "#b8b8b8")
var y = d3.scaleLinear()
.domain([0, 1000000000])
.range([ height, 0 ]);
var stackedData = d3.stack()
.offset(d3.stackOffsetSilhouette)
.keys(keys)
(data)
var area = d3.area()
.x(function(d) { return x(new Date(d.data.date)); })
.y0(function(d) { return y(d[0]); })
.y1(function(d) { return y(d[1]); });
svg
.selectAll("mylayers")
.data(stackedData)
.enter()
.append("path")
.attr("class", "myArea")
.style("fill", "#003366")
.attr("d", area);
<script src="https://d3js.org/d3.v5.min.js"></script>
正如我们所见,图表未显示,但同时未标记任何错误。
问题
鉴于代码的简单性和与看到的功能齐全的模板的相似性 here,为什么此图无法按预期呈现?
我认为您需要将日期转换为数值,这样的一些代码可能会有所帮助
var dateParser = d3.timeParse('%b-%y')
var area = d3.area()
.x(function(d) { return x(dateParser(d.data.date)); })
.y0(function(d) { return y(d[0]); })
.y1(function(d) { return y(d[1]); });
这是一个工作示例:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<script>
const margin = { top: 20, right: 20, bottom: 20, left: 20 },
width = 900 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom;
const svg = d3.select("body")
.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})`);
const parseDate = d3.timeParse('%b-%y');
var data = [{
'active': 56733306054.0,
'bond': 3525783856.0,
'date': 'Apr-15',
'mmf': 1403672993.0,
'other': 0.0,
'passive': 6821599781.0
},
{
'active': 5716791269.0,
'bond': 6085973929.0,
'date': 'Jul-15',
'mmf': 3941955156.0,
'other': 0.0,
'passive': 669757365.2
},
{
'active': 17062997217.0,
'bond': 4039598099.0,
'date': 'Oct-15',
'mmf': 4009017950.0,
'other': 0.0,
'passive': 726136994.3
},
{
'active': 7814464858.0,
'bond': 4262416085.0,
'date': 'Jan-16',
'mmf': 6942848526.0,
'other': 1868408693.0,
'passive': 576693480.6
},
{
'active': 3225887820.0,
'bond': 1997520654.0,
'date': 'Apr-16',
'mmf': 8803909471.0,
'other': 1829867764.0,
'passive': 658579093.5
},
{
'active': 7552865110.0,
'bond': 2774538610.0,
'date': 'Jul-16',
'mmf': 17168667665.0,
'other': 1781624412.0,
'passive': 1062492998.0
},
{
'active': 9921160101.0,
'bond': 4749422921.0,
'date': 'Oct-16',
'mmf': 19897031580.0,
'other': 1642076470.0,
'passive': 1001209305.0
},
{
'active': 11432914047.0,
'bond': 6282916561.0,
'date': 'Jan-17',
'mmf': 10962414198.0,
'other': 1540325097.0,
'passive': 1865670585.0
},
{
'active': 12239976192.0,
'bond': 5161108076.0,
'date': 'Apr-17',
'mmf': 7858159818.0,
'other': 1423157123.0,
'passive': 1394368561.0
},
{
'active': 12538521595.0,
'bond': 4844007015.0,
'date': 'Jul-17',
'mmf': 10153574680.0,
'other': 1327231248.0,
'passive': 982569223.9
},
{
'active': 13660436312.0,
'bond': 4831471993.0,
'date': 'Oct-17',
'mmf': 9105515290.0,
'other': 1226448389.0,
'passive': 660421454.6
},
{
'active': 18238784924.0,
'bond': 6926050754.0,
'date': 'Jan-18',
'mmf': 8997606297.0,
'other': 0.0,
'passive': 502423215.8
},
{
'active': 16515400278.0,
'bond': 8174797500.0,
'date': 'Apr-18',
'mmf': 10488139471.0,
'other': 0.0,
'passive': 641632439.9
},
{
'active': 14469020809.0,
'bond': 10154350717.0,
'date': 'Jul-18',
'mmf': 12795032278.0,
'other': 0.0,
'passive': 373254191.0
},
{
'active': 11941160301.0,
'bond': 11565983214.0,
'date': 'Oct-18',
'mmf': 9868174645.0,
'other': 0.0,
'passive': 500573365.9
},
{
'active': 13065033332.0,
'bond': 13150111094.0,
'date': 'Jan-19',
'mmf': 9383725064.0,
'other': 0.0,
'passive': 348729651.5
},
{
'active': 13015515107.0,
'bond': 13530625221.0,
'date': 'Apr-19',
'mmf': 10134077571.0,
'other': 0.0,
'passive': 289549779.9
},
{
'active': 15803115946.0,
'bond': 16503245488.0,
'date': 'Jul-19',
'mmf': 10938147334.0,
'other': 0.0,
'passive': 364098177.7
},
{
'active': 19281878473.0,
'bond': 22592356870.0,
'date': 'Oct-19',
'mmf': 13042415142.0,
'other': 0.0,
'passive': 1182250058.0
},
{
'active': 26486960563.0,
'bond': 26446208720.0,
'date': 'Jan-20',
'mmf': 14980167197.0,
'other': 0.0,
'passive': 825650931.1
},
{
'active': 26551390384.0,
'bond': 27921669739.0,
'date': 'Apr-20',
'mmf': 9558841841.0,
'other': 0.0,
'passive': 841110171.1
},
{
'active': 26498733168.0,
'bond': 23387500164.0,
'date': 'Jul-20',
'mmf': 9754774244.0,
'other': 0.0,
'passive': 930687399.1
},
{
'active': 30362195233.0,
'bond': 25104023352.0,
'date': 'Oct-20',
'mmf': 14576442586.0,
'other': 0.0,
'passive': 981491044.5
},
{
'active': 33018698783.0,
'bond': 19038462941.0,
'date': 'Jan-21',
'mmf': 15537675080.0,
'other': 0.0,
'passive': 875201720.9
},
{
'active': 50881100695.0,
'bond': 15108333888.0,
'date': 'Apr-21',
'mmf': 17027529982.0,
'other': 0.0,
'passive': 781991391.3
}].map(d => {
d['date'] = parseDate(d['date']);
return d;
});
const keys = ['bond', 'active', 'passive', 'mmf', 'other'];
const x = d3.scaleTime()
.domain(d3.extent(data, d => d.date))
.range([0, width]);
svg.append("g")
.attr("transform", `translate(0,${height})`)
.call(
d3.axisBottom(x)
.tickSize(-height)
)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").attr("stroke", "#b8b8b8"));
/*
code from https://observablehq.com/@d3/streamgraph
The d3-shape docs say that d3.stackOffsetWiggle "Shifts the baseline
so as to minimize the weighted wiggle of layers. This offset is recommended
for streamgraphs in conjunction with the inside-out order."
*/
const stackedData = d3.stack()
.order(d3.stackOrderInsideOut)
.offset(d3.stackOffsetWiggle)
.keys(keys)
(data);
// the domain of the y-scale should cover the min and max of the stacked data
// code from https://observablehq.com/@d3/streamgraph
const y = d3.scaleLinear()
.domain([
d3.min(stackedData, d => d3.min(d, d => d[0])),
d3.max(stackedData, d => d3.max(d, d => d[1]))
])
.range([height, 0]);
const color = d3.scaleOrdinal()
.domain(keys)
.range(d3.schemeCategory10);
const area = d3.area()
.x(d => x(d.data.date))
.y0(d => y(d[0]))
.y1(d => y(d[1]));
svg.append('g')
.selectAll("path")
.data(stackedData)
.join("path")
.style("fill", d => color(d.key))
.attr("d", area);
</script>
</body>
正如 James 的回答所说,您应该使用 d3.timeParse
将字符串转换为日期,而不是依赖 Date()
构造函数,即 unreliable。此外,您的 keys
数组应仅包含堆叠的属性,因此不应包含“日期”。
我为 d3.stackOffsetWiggle
引用了 Mike Bostock's streamgraph example for the stack generator and the y-scale. The d3-shape docs 说它“移动基线以最小化图层的加权摆动。建议将此偏移量与由内而外的顺序一起用于流图。 “我遵循该建议而不是使用 d3.stackOffsetSilhouette
。最后,按照示例,y 尺度的域应覆盖堆叠数据的最小值和最大值。