带有条形图的 d3 堆叠条形图不会在转换中更新
d3 stacked bar with bars don't update in a transition
按照这个问题的顺序 (),我使用 D3 应用了一个转换来更改堆叠条形图的数据。
我的轴对这个新数据集进行了完美的过渡和修改,但水平条仍然没有动过。
我已经尝试过 Lars (d3.js bar charts transitioning between multiple csv files) 的这个解决方案,但我仍然可以看到条形图发生了变化。
我的代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" class="ocks-org do-not-copy">
<head>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div><button class="btn btn-mini" id="backButton" onclick="updateData();">Update</button></div>
<div id="timeLine"></div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var timeline;
var margin = {
top : 20,
right : 10,
bottom : 60,
left : 80
},
width = 500 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.rangeRound([0, width]);
var y = d3.scale.ordinal()
.rangeBands([height, 0], 0.1);
var color = d3.scale.ordinal()
.range(["#1f77b4", "#2ca02c", "#E53524"]);
//var color = d3.scale.category10()
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(d3.format(".2s"))
.ticks(10);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5);
timeline = d3.select("#timeLine").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 dataSet;
dataSet = [{
"Date" : "2014-01",
"insert" : "2",
"remove" : "17",
"updates" : "27"
}, {
"Date" : "2014-02",
"insert" : "27",
"remove" : "127",
"updates" : "47"
}, {
"Date" : "2014-03",
"insert" : "227",
"remove" : "17",
"updates" : "42"
}, {
"Date" : "2014-04",
"insert" : "0",
"remove" : "0",
"updates" : "0"
}, {
"Date" : "2014-05",
"insert" : "127",
"remove" : "1",
"updates" : "423"
},
];
color.domain(d3.keys(dataSet[0]).filter(function (key) {
return key !== "Date";
}));
dataSet.forEach(function (d) {
var x0 = 0;
d.ages = color.domain().map(function (name) {
return {
name : name,
x0 : x0,
x1 : x0 += +d[name]
};
});
d.total = d.ages[d.ages.length - 1].x1;
});
yAxis.tickFormat(function (d) {
var val = 0;
dataSet.forEach(function (item) {
if (item.Date == d)
val = item.total;
});
return val == 0 ? "" : d;
});
y.domain(dataSet.map(function (d) {
return d.Date;
}));
x.domain([0, d3.max(dataSet, function (d) {
return (d.total + 5);
})]);
timeline.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", 1)
.attr("dx", "42em")
.attr("dy", "3em")
.style("text-anchor", "end")
.text("Operations");
timeline.append("g")
.attr("class", "y axis")
.call(yAxis);
var layer = timeline.selectAll(".state")
.data(dataSet)
.enter().append("g")
.attr("class", "rect")
.attr("transform", function (d) {
return "translate(0," + y(d.Date) + ")";
});
var rect = layer.selectAll("rect")
.data(function (d) {
return d.ages;
})
.enter().append("rect")
.attr("class", "rect")
.attr("width", 0)
.attr("x", width)
.attr('y', function (d, i) {
return y(d.Date);
})
.attr("height", y.rangeBand())
.style("fill", function (d) {
return color(d.name);
});
rect.transition()
.duration(600)
.delay(function (d, i) {
return i * 300;
})
.attr("width", function (d) {
return x(d.x1) - x(d.x0);
})
.attr("x", function (d) {
return x(d.x0);
});
function updateData() {
dataSet = [{
"Date" : "2014-11",
"insert" : "27",
"remove" : "1723",
"updates" : "7"
}, {
"Date" : "2014-12",
"insert" : "237",
"remove" : "12",
"updates" : "433"
}, {
"Date" : "2015-03",
"insert" : "22",
"remove" : "172",
"updates" : "423"
}, {
"Date" : "2015-05",
"insert" : "17",
"remove" : "122",
"updates" : "42"
}, {
"Date" : "2015-04",
"insert" : "0",
"remove" : "0",
"updates" : "0"
}
];
dataSet.forEach(function (d) {
var x0 = 0;
d.ages = color.domain().map(function (name) {
return {
name : name,
x0 : x0,
x1 : x0 += +d[name]
};
});
d.total = d.ages[d.ages.length - 1].x1;
});
yAxis.tickFormat(function (d) {
var val = 0;
dataSet.forEach(function (item) {
if (item.Date == d)
val = item.total;
});
return val == 0 ? "" : d;
});
y.domain(dataSet.map(function (d) {
return d.Date;
}));
x.domain([0, d3.max(dataSet, function (d) {
return (d.total + 5);
})]);
// Make the changes
var transition = timeline.transition().duration(750),
delay = function (d, i) {
return i * 50;
};
// update bars
//var teste = timeline.selectAll(".state").data(dataSet);
var layer = timeline.selectAll(".state").data(dataSet).enter().append("g")
.attr("class", "rect")
.attr("transform", function (d) {
return "translate(0," + y(d.Date) + ")";
});
var sel = layer.selectAll("rect")
.data(function (d) {
return d.ages;
})
.enter().append("rect")
.attr("class", "rect")
.attr("width", 0)
.attr("x", width)
.attr('y', function (d, i) {
return y(d.Date);
})
//.attr("height", y.rangeBand())
.attr("height", y.rangeBand())
.style("fill", function (d) {
return color(d.name);
});
//remove bars no longer present - DON'T WORK
//sel.exit().remove();
sel.transition()
.duration(600)
.delay(function (d, i) {
return i * 300;
})
.attr("x", function (d) {
return x(d.x0);
}).attr("width", function (d) {
return x(d.x1) - x(d.x0);
})
.attr('y', function (d, i) {
return y(d.Date);
})
.attr("height", y.rangeBand());
transition.select(".y.axis") // change the y axis
.call(yAxis);
transition.select(".x.axis") // change the x axis
.call(xAxis);
}
</script>
</body>
</html>
谢谢,
菲利普
让我们跳过代码的组织。
主要错误是您尝试访问未定义的变量。
首先,当您构建堆叠条形图时,您会这样做:
var rect = layer.selectAll("rect")
.data(function (d) {
return d.ages;
})
将 "d.ages" 中的值关联到每个矩形,因此您可以访问 "d.x0" 和 "d.x1"。在更新函数中,您尝试直接访问不存在的 "d.x0" 和 "d.x1",因为它们位于 ages 元素中。
你在主函数中的数据集项:
Object {name: "insert", x0: 0, x1: 2}
更新函数中你的数据集项:
Object {Date: "2015-03", insert: "22", remove: "172", updates: "423", ages: Array[3]…}
然后在年龄:
ages: Array[3]
0: Object
name: "insert"
x0: 0
x1: 22
......................
按照这个问题的顺序 (
我的轴对这个新数据集进行了完美的过渡和修改,但水平条仍然没有动过。 我已经尝试过 Lars (d3.js bar charts transitioning between multiple csv files) 的这个解决方案,但我仍然可以看到条形图发生了变化。
我的代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" class="ocks-org do-not-copy">
<head>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div><button class="btn btn-mini" id="backButton" onclick="updateData();">Update</button></div>
<div id="timeLine"></div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var timeline;
var margin = {
top : 20,
right : 10,
bottom : 60,
left : 80
},
width = 500 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.rangeRound([0, width]);
var y = d3.scale.ordinal()
.rangeBands([height, 0], 0.1);
var color = d3.scale.ordinal()
.range(["#1f77b4", "#2ca02c", "#E53524"]);
//var color = d3.scale.category10()
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(d3.format(".2s"))
.ticks(10);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5);
timeline = d3.select("#timeLine").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 dataSet;
dataSet = [{
"Date" : "2014-01",
"insert" : "2",
"remove" : "17",
"updates" : "27"
}, {
"Date" : "2014-02",
"insert" : "27",
"remove" : "127",
"updates" : "47"
}, {
"Date" : "2014-03",
"insert" : "227",
"remove" : "17",
"updates" : "42"
}, {
"Date" : "2014-04",
"insert" : "0",
"remove" : "0",
"updates" : "0"
}, {
"Date" : "2014-05",
"insert" : "127",
"remove" : "1",
"updates" : "423"
},
];
color.domain(d3.keys(dataSet[0]).filter(function (key) {
return key !== "Date";
}));
dataSet.forEach(function (d) {
var x0 = 0;
d.ages = color.domain().map(function (name) {
return {
name : name,
x0 : x0,
x1 : x0 += +d[name]
};
});
d.total = d.ages[d.ages.length - 1].x1;
});
yAxis.tickFormat(function (d) {
var val = 0;
dataSet.forEach(function (item) {
if (item.Date == d)
val = item.total;
});
return val == 0 ? "" : d;
});
y.domain(dataSet.map(function (d) {
return d.Date;
}));
x.domain([0, d3.max(dataSet, function (d) {
return (d.total + 5);
})]);
timeline.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", 1)
.attr("dx", "42em")
.attr("dy", "3em")
.style("text-anchor", "end")
.text("Operations");
timeline.append("g")
.attr("class", "y axis")
.call(yAxis);
var layer = timeline.selectAll(".state")
.data(dataSet)
.enter().append("g")
.attr("class", "rect")
.attr("transform", function (d) {
return "translate(0," + y(d.Date) + ")";
});
var rect = layer.selectAll("rect")
.data(function (d) {
return d.ages;
})
.enter().append("rect")
.attr("class", "rect")
.attr("width", 0)
.attr("x", width)
.attr('y', function (d, i) {
return y(d.Date);
})
.attr("height", y.rangeBand())
.style("fill", function (d) {
return color(d.name);
});
rect.transition()
.duration(600)
.delay(function (d, i) {
return i * 300;
})
.attr("width", function (d) {
return x(d.x1) - x(d.x0);
})
.attr("x", function (d) {
return x(d.x0);
});
function updateData() {
dataSet = [{
"Date" : "2014-11",
"insert" : "27",
"remove" : "1723",
"updates" : "7"
}, {
"Date" : "2014-12",
"insert" : "237",
"remove" : "12",
"updates" : "433"
}, {
"Date" : "2015-03",
"insert" : "22",
"remove" : "172",
"updates" : "423"
}, {
"Date" : "2015-05",
"insert" : "17",
"remove" : "122",
"updates" : "42"
}, {
"Date" : "2015-04",
"insert" : "0",
"remove" : "0",
"updates" : "0"
}
];
dataSet.forEach(function (d) {
var x0 = 0;
d.ages = color.domain().map(function (name) {
return {
name : name,
x0 : x0,
x1 : x0 += +d[name]
};
});
d.total = d.ages[d.ages.length - 1].x1;
});
yAxis.tickFormat(function (d) {
var val = 0;
dataSet.forEach(function (item) {
if (item.Date == d)
val = item.total;
});
return val == 0 ? "" : d;
});
y.domain(dataSet.map(function (d) {
return d.Date;
}));
x.domain([0, d3.max(dataSet, function (d) {
return (d.total + 5);
})]);
// Make the changes
var transition = timeline.transition().duration(750),
delay = function (d, i) {
return i * 50;
};
// update bars
//var teste = timeline.selectAll(".state").data(dataSet);
var layer = timeline.selectAll(".state").data(dataSet).enter().append("g")
.attr("class", "rect")
.attr("transform", function (d) {
return "translate(0," + y(d.Date) + ")";
});
var sel = layer.selectAll("rect")
.data(function (d) {
return d.ages;
})
.enter().append("rect")
.attr("class", "rect")
.attr("width", 0)
.attr("x", width)
.attr('y', function (d, i) {
return y(d.Date);
})
//.attr("height", y.rangeBand())
.attr("height", y.rangeBand())
.style("fill", function (d) {
return color(d.name);
});
//remove bars no longer present - DON'T WORK
//sel.exit().remove();
sel.transition()
.duration(600)
.delay(function (d, i) {
return i * 300;
})
.attr("x", function (d) {
return x(d.x0);
}).attr("width", function (d) {
return x(d.x1) - x(d.x0);
})
.attr('y', function (d, i) {
return y(d.Date);
})
.attr("height", y.rangeBand());
transition.select(".y.axis") // change the y axis
.call(yAxis);
transition.select(".x.axis") // change the x axis
.call(xAxis);
}
</script>
</body>
</html>
谢谢, 菲利普
让我们跳过代码的组织。 主要错误是您尝试访问未定义的变量。 首先,当您构建堆叠条形图时,您会这样做:
var rect = layer.selectAll("rect")
.data(function (d) {
return d.ages;
})
将 "d.ages" 中的值关联到每个矩形,因此您可以访问 "d.x0" 和 "d.x1"。在更新函数中,您尝试直接访问不存在的 "d.x0" 和 "d.x1",因为它们位于 ages 元素中。
你在主函数中的数据集项:
Object {name: "insert", x0: 0, x1: 2}
更新函数中你的数据集项:
Object {Date: "2015-03", insert: "22", remove: "172", updates: "423", ages: Array[3]…}
然后在年龄:
ages: Array[3]
0: Object
name: "insert"
x0: 0
x1: 22
......................