指定 base/floor 的 D3 面积图
D3 Area chart with specified base/floor
是否可以在 D3 中制作面积图,我可以在其中指定面积图的底部(作为另一个图)。
像这样:
所以地板不是总是在 Y=0,它实际上是从 y=1.03^X
导出的图
这是我的代码:
var NSW = "NSW";
var QLD = "QLD";
var width = 600;
var height = 400;
var years = [];
var getStat = function(year, volatility, basis) {
// volatility = 0.04;
// basis = 1.11;
return {
d: year,
x: basis,
vol: volatility,
value: 45 * Math.pow(basis, year),
high: 45 * Math.pow(basis+volatility, year),
low: 45 * Math.pow(basis-volatility, year),
}
}
for(i = 0; i < 25; i++) {
years.push(i);
}
var data = years.map(function(year){ return [getStat(year, 0.04, 1.11),getStat(year, 0.02, 1.07)]; }); // generate bogus data
var nsw = data.map(function(d) { return d[0].value;}); // extract new south wales data
var qld = data.map(function(d) { return d[1].value;}); // extract queensland data
var chart = d3.select("#chart").attr("width", width).attr("height", height).append("g");
var x = d3.scale.linear().domain([0, years.length]).range([0, width]);
var y = d3.scale.linear().domain([0, d3.max(data, function(d){ return Math.max(d[0].high, d[1].high); })]).range([height,0]);
var area = d3.svg.area().x(function(d,i) { return x(i); }).y0(height).y1(function(d, i) { return y(d); })
console.log([nsw,qld])
chart
.selectAll("path.area")
.data([nsw,qld]) // !!! here i can pass both arrays in.
.enter()
.append("path")
.attr("fill", "rgba(0,0,0,0.5)")
.attr("class", function(d,i) { return [NSW,QLD][i]; })
.attr("d", area);
还有我的 HTML:
<svg id="chart"></svg>
这里有一个例子,可以帮助您理解上下文。
var area = d3.svg.area()
.x(function(d) { return x(d.xValue); })
.y0(height)
.y1(function(d) { return y(d.xValue^3); });
现在,当您执行此操作时,底部 y0 固定在当前图表底部的全高处。但基本上 y0,y1 都是访问函数。所以基本上你每次为每个数据值将高度传递给 y0。现在,如果你把它改成这样:
var area = d3.svg.area()
.x(function(d) { return x(d.xValue); })
.y0(function(d){ return y(d.xValue/2);}) //FUNCTION FOR BASE-Y
.y1(function(d) { return y(d.xValue^3); }); //FUNCTION FOR TOP-Y
现在理想情况下,您的面积图的基础会相应地发生变化。我希望这可以帮助您实现您正在尝试的目标。如果解决方案没有按预期工作,请告诉我。如果需要,我会创建一个 fiddle。
编辑:针对您问题的变化,您要绘制的每个区域都必须有自己的功能。现在这将需要您编写多个区域函数,这些函数仅适用于一个或两个区域。但是,如果您打算用多个彩色区域填充整个图表,我相信您需要先使用它 d3 stack layout
在概念中,堆栈布局会重新排列您的数据,以便返回的布局对象基本上包含多个数组(我说数组是因为它使理解实际结构变得简单,我猜想在编写函数时用于映射)。现在您需要一个单独的区域函数,可以为返回的布局中的每个实例迭代调用该函数。对于每个实例,我指的是不同的数组,当传递给 area 函数时会产生不同的结果 areas.I 希望我的解释能有所帮助,但我自己是这个主题的新手,所以这里有一个例子会有所帮助:Stacked Area Chart
这是执行此操作的理想方法,如果您不介意一个简单的解决方法,那么这就是我目前正在做的事情:说现在而不只是 [nsw,qld] 您想要绘制区域[nsw1,qld1],[nsw2,qld2],......等等。
iterationData = [[nsw,qld],[nsw1,qld1],[nsw2,qld2],........];
for(i in iterationData){
chart
.data(iterationData[i])
.append("path")
.attr("fill", "fixed_color_value/color_scale(category10/category20)")
.attr("class", function(d,i) { return [NSW,QLD][i]; })
.attr("d", area);
}
希望这能彻底回答您的问题。
是否可以在 D3 中制作面积图,我可以在其中指定面积图的底部(作为另一个图)。
像这样:
所以地板不是总是在 Y=0,它实际上是从 y=1.03^X
导出的图这是我的代码:
var NSW = "NSW";
var QLD = "QLD";
var width = 600;
var height = 400;
var years = [];
var getStat = function(year, volatility, basis) {
// volatility = 0.04;
// basis = 1.11;
return {
d: year,
x: basis,
vol: volatility,
value: 45 * Math.pow(basis, year),
high: 45 * Math.pow(basis+volatility, year),
low: 45 * Math.pow(basis-volatility, year),
}
}
for(i = 0; i < 25; i++) {
years.push(i);
}
var data = years.map(function(year){ return [getStat(year, 0.04, 1.11),getStat(year, 0.02, 1.07)]; }); // generate bogus data
var nsw = data.map(function(d) { return d[0].value;}); // extract new south wales data
var qld = data.map(function(d) { return d[1].value;}); // extract queensland data
var chart = d3.select("#chart").attr("width", width).attr("height", height).append("g");
var x = d3.scale.linear().domain([0, years.length]).range([0, width]);
var y = d3.scale.linear().domain([0, d3.max(data, function(d){ return Math.max(d[0].high, d[1].high); })]).range([height,0]);
var area = d3.svg.area().x(function(d,i) { return x(i); }).y0(height).y1(function(d, i) { return y(d); })
console.log([nsw,qld])
chart
.selectAll("path.area")
.data([nsw,qld]) // !!! here i can pass both arrays in.
.enter()
.append("path")
.attr("fill", "rgba(0,0,0,0.5)")
.attr("class", function(d,i) { return [NSW,QLD][i]; })
.attr("d", area);
还有我的 HTML:
<svg id="chart"></svg>
这里有一个例子,可以帮助您理解上下文。
var area = d3.svg.area()
.x(function(d) { return x(d.xValue); })
.y0(height)
.y1(function(d) { return y(d.xValue^3); });
现在,当您执行此操作时,底部 y0 固定在当前图表底部的全高处。但基本上 y0,y1 都是访问函数。所以基本上你每次为每个数据值将高度传递给 y0。现在,如果你把它改成这样:
var area = d3.svg.area()
.x(function(d) { return x(d.xValue); })
.y0(function(d){ return y(d.xValue/2);}) //FUNCTION FOR BASE-Y
.y1(function(d) { return y(d.xValue^3); }); //FUNCTION FOR TOP-Y
现在理想情况下,您的面积图的基础会相应地发生变化。我希望这可以帮助您实现您正在尝试的目标。如果解决方案没有按预期工作,请告诉我。如果需要,我会创建一个 fiddle。
编辑:针对您问题的变化,您要绘制的每个区域都必须有自己的功能。现在这将需要您编写多个区域函数,这些函数仅适用于一个或两个区域。但是,如果您打算用多个彩色区域填充整个图表,我相信您需要先使用它 d3 stack layout
在概念中,堆栈布局会重新排列您的数据,以便返回的布局对象基本上包含多个数组(我说数组是因为它使理解实际结构变得简单,我猜想在编写函数时用于映射)。现在您需要一个单独的区域函数,可以为返回的布局中的每个实例迭代调用该函数。对于每个实例,我指的是不同的数组,当传递给 area 函数时会产生不同的结果 areas.I 希望我的解释能有所帮助,但我自己是这个主题的新手,所以这里有一个例子会有所帮助:Stacked Area Chart
这是执行此操作的理想方法,如果您不介意一个简单的解决方法,那么这就是我目前正在做的事情:说现在而不只是 [nsw,qld] 您想要绘制区域[nsw1,qld1],[nsw2,qld2],......等等。
iterationData = [[nsw,qld],[nsw1,qld1],[nsw2,qld2],........];
for(i in iterationData){
chart
.data(iterationData[i])
.append("path")
.attr("fill", "fixed_color_value/color_scale(category10/category20)")
.attr("class", function(d,i) { return [NSW,QLD][i]; })
.attr("d", area);
}
希望这能彻底回答您的问题。