Javascript 调整发散堆积条形图以使用通用更新模式
我一直在使用具有以下代码的堆叠条形图示例:Javascript 调整发散堆积条形图以使用通用更新模式,javascript,d3.js,Javascript,D3.js,我一直在使用具有以下代码的堆叠条形图示例: var data = [ {month: "Q1-2016", apples: 3840, bananas: 1920, cherries: -1960, dates: -400}, {month: "Q2-2016", apples: 1600, bananas: 1440, cherries: -960, dates: -400}, {month: "Q3-2016", apples: 640, bananas: 960, cher
var data = [
{month: "Q1-2016", apples: 3840, bananas: 1920, cherries: -1960, dates: -400},
{month: "Q2-2016", apples: 1600, bananas: 1440, cherries: -960, dates: -400},
{month: "Q3-2016", apples: 640, bananas: 960, cherries: -640, dates: -600},
{month: "Q4-2016", apples: 320, bananas: 480, cherries: -640, dates: -400}
];
var series = d3.stack()
.keys(["apples", "bananas", "cherries", "dates"])
.offset(d3.stackOffsetDiverging)
(data);
var svg = d3.select("svg"),
margin = {top: 20, right: 30, bottom: 30, left: 60},
width = +svg.attr("width"),
height = +svg.attr("height");
var x = d3.scaleBand()
.domain(data.map(function(d) { return d.month; }))
.rangeRound([margin.left, width - margin.right])
.padding(0.1);
var y = d3.scaleLinear()
.domain([d3.min(series, stackMin), d3.max(series, stackMax)])
.rangeRound([height - margin.bottom, margin.top]);
var z = d3.scaleOrdinal(d3.schemeCategory10);
svg.append("g")
.selectAll("g")
.data(series)
.enter().append("g")
.attr("fill", function(d) { return z(d.key); })
.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("width", x.bandwidth)
.attr("x", function(d) { return x(d.data.month); })
.attr("y", function(d) { return y(d[1]); })
.attr("height", function(d) { return y(d[0]) - y(d[1]); })
svg.append("g")
.attr("transform", "translate(0," + y(0) + ")")
.call(d3.axisBottom(x));
svg.append("g")
.attr("transform", "translate(" + margin.left + ",0)")
.call(d3.axisLeft(y));
function stackMin(serie) {
return d3.min(serie, function(d) { return d[0]; });
}
function stackMax(serie) {
return d3.max(serie, function(d) { return d[1]; });
}
示例中的代码不支持转换或重画,所以我一直在尝试将的原则应用于它,以便在我的应用程序中使用它
我不熟悉D3v4,而“附件”的性质让我感到困惑。我在同一个append方法链中看到两个“enter”,因此我尝试将它们分离到各自的声明中,如:
var join1 = .selectAll("g")
.data(series)
var join2Update = .selectAll("rect")
.data(function(d) { return d; })
var join2Enter= join2.enter()
join2Enter
.append("rect")
.merge(join2Update)
.transition()
.attr("width", x.bandwidth)
.attr("x", function(d) { return x(d.data.month); })
.attr("y", function(d) { return y(d[1]); })
.attr("height", function(d) { return y(d[0]) - y(d[1]); })
但除了打破图表,它没什么作用!坦白地说,我对整个过程有点茫然,任何帮助都将不胜感激。我对您的代码做了一些修改,以使其可更新,我将指出我所做的一些修改,如果还有什么不清楚的地方,您可以问 我更改的主要内容是,为了简单起见,在数据集中我们有两个类别,这样我们就可以根据这样的输入更新数据
var keys = ["apples" + input, "bananas" + input];
d3.selectAll(".opt").on("change", function() {
update(data, this.value)
})
这里的输入变量最初是这样选择的
var input = d3.selectAll(".opt").property("value");
当我们手动更新它时,我们会得到这样的新数据
var keys = ["apples" + input, "bananas" + input];
d3.selectAll(".opt").on("change", function() {
update(data, this.value)
})
我们创建了一个条形组来保存系列
数据集,并在以后使用另一个变量引用它,而不是直接将g元素与rect一起添加
var barGroups = svg.selectAll("g.layer")
.data(series);
barGroups.exit().remove();
barGroups.enter().insert("g", ".x-axis")
.classed('layer', true);
下面是您前面提到的代码的更新模式部分:
var bars = svg.selectAll("g.layer").selectAll("rect")
.data(function(d) { return d; });
bars.exit().remove();
bars = bars
.enter()
.append("rect")
.attr("width", x.bandwidth())
.attr("x", d => x(d.data.month))
.merge(bars)
bars.transition().duration(750)
.attr("y", d => y(d[1]))
.attr("height", d => Math.abs(y(d[0])) - y(d[1]));
应该就是这样,看看下面的代码片段,看看它是如何工作的
var数据=[
{月份:“2016年第一季度”,苹果1:400,香蕉1:920,苹果2:196,香蕉2:840},
{月份:“2016年第二季度”,苹果1:400,香蕉1:440,苹果2:960,香蕉2:600},
{月份:“2016年第三季度”,苹果1:-600,香蕉1:960,苹果2:-640,香蕉2:640},
{月份:“2016年第四季度”,苹果1:400,香蕉1:480,苹果2:640,香蕉2:320}
];
var margin={顶部:35,右侧:145,底部:35,左侧:45},
宽度=650-边距。左侧-边距。右侧,
高度=450-边距.顶部-边距.底部;
var svg=d3。选择(“图表”)
.attr(“宽度”,宽度+边距。左侧+边距。右侧)
.attr(“高度”,高度+边距。顶部+边距。底部)
.附加(“g”)
.attr(“转换”、“平移”(+margin.left+)、“+margin.top+”);
var x=d3.scaleBand()
.rangeRound([0,宽度])
.填充(0.1);
变量y=d3.scaleLinear()
.rangeRound([高度,0]);
var z=d3.scaleOrdinal()
.范围([“钢蓝”、“达科朗格”);
svg.append(“g”)
.attr(“类”、“x轴”);
svg.append(“g”)
.attr(“类”、“y轴”);
var输入=d3.selectAll(“.opt”).property(“value”);
d3.选择全部(“.opt”)。打开(“更改”,函数(){
更新(数据,此.value)
})
更新(数据、输入);
功能更新(数据、输入){
变量键=[“苹果”+输入,“香蕉”+输入];
var series=d3.stack()
.钥匙(钥匙)
.偏移(d3.堆栈偏移发散)
(数据);
x、 域(data.map(d=>d.month));
y、 领域([
d3.最小值(系列,最小值),
d3.max(系列,stackMax)
]).nice();
var barGroups=svg.selectAll(“g.layer”)
.数据(系列);
barGroups.exit().remove();
barGroups.enter().insert(“g”、“.x轴”)
.classed('层',真);
svg.selectAll(“g.layer”)
.transition().持续时间(750)
.attr(“填充”,d=>z(d.key));
var bar=svg.selectAll(“g.layer”).selectAll(“rect”)
.data(函数(d){返回d;});
bar.exit().remove();
钢筋=钢筋
.输入()
.append(“rect”)
.attr(“宽度”,x.带宽())
.attr(“x”,d=>x(d.data.month))
.合并(条)
bar.transition().持续时间(750)
.attr(“y”,d=>y(d[1]))
.attr(“height”,d=>Math.abs(y(d[0]))-y(d[1]);
svg.selectAll(“.x轴”).transition().持续时间(750)
.attr(“变换”、“平移(0)、+y(0)+”)
.call(d3.axisBottom(x));
svg.selectAll(“.y轴”).transition().持续时间(750)
.调用(d3.左(y));
函数stackMin(系列){
返回d3.min(序列,函数(d){返回d[0];});
}
函数stackMax(系列){
返回d3.max(序列,函数(d){返回d[1];});
}
}
正文{
保证金:自动;
宽度:850px;
}
挑选
1.
2.
这是一个极好的答案。谢谢你抽出时间来做这件事。我可以在代码中更清楚地看到更新模式的应用。不幸的是,我在转换方面遇到了问题,但这是因为我在一个Ember组件中实现了上述内容,这超出了原始问题的范围。@Abuelo没问题,很抱歉听到这个消息,我相信有人能够胜任Ember的工作,可以帮助您。