我已经和d3 v4合作了几个月并做了很多研究。我终于抓住了数据连接概念,但试图弄清楚如何更新分组条形图。“
我认为我的问题是我在执行连接时没有选择正确的SVG元素,因此update()
和exit()
方法总是返回空集。以下是基于d3广告代码的代码:Codepen请参阅#135 行,其中所有魔法都假设正在发生。
/* Based on https://bl.ocks.org/mbostock/3887051 */
var svg = d3.select("svg"),
margin = { top: 20, right: 20, bottom: 100, left: 40 },
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var formatTime = d3.timeFormat("%X");
var legendKeys = new Map();
var x0 = d3
.scaleBand()
.rangeRound([0, width])
.paddingInner(0.1);
var x1 = d3.scaleBand().padding(0.05);
var y = d3.scaleLinear().rangeRound([height, 0]);
var z = d3
.scaleOrdinal()
.range([
"#98abc5",
"#8a89a6",
"#7b6888",
"#6b486b",
"#a05d56",
"#d0743c",
"#ff8c00"
]);
var data = [];
for (var i = 0; i < 5; i++) {
generateData();
}
var keys = Object.keys(data[0].y);
keys.forEach(k => legendKeys.set(".data-" + k.replace(/ /g, "")));
g.append("g").attr("class", "bars");
var xAxis = g
.append("g")
.attr("class", "x--axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x0).tickFormat(formatTime));
var yAxis = g
.append("g")
.attr("class", "y--axis")
.call(d3.axisLeft(y).ticks(null, "s"));
var legend = g
.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 8)
.attr("text-anchor", "end")
.attr("class", "legend")
.selectAll("g")
.data(keys.slice())
.enter()
.append("g")
.attr("transform", function(d, i) {
return "translate(0," + i * 20 + ")";
});
legend
.append("rect")
.attr("x", width - 19)
.attr("width", 19)
.attr("height", 19)
.attr("style", "cursor:pointer")
.attr("fill", z)
.on("click", function(d) {
var key = ".data-" + d.replace(/ /g, "");
// determine if current line is visible
var active = legendKeys.get(key) ? false : true,
newOpacity = active ? 0 : 1;
// hide or show the elements
d3.selectAll(key).style("opacity", newOpacity);
// update whether or not the elements are active
legendKeys.set(key, active);
this.style.opacity = active ? 0.5 : 1;
});
legend
.append("text")
.attr("x", width - 24)
.attr("y", 9.5)
.attr("dy", "0.32em")
.text(function(d) {
return d;
});
window.setInterval(() => {
generateData();
if (data.length > 14) {
data.shift();
}
updateChart();
}, 1000);
function updateChart() {
x0.domain(
data.map(function(d) {
return d.x;
})
);
x1.domain(keys).rangeRound([0, x0.bandwidth()]);
y
.domain([
0,
d3.max(data, function(d) {
return d3.max(keys, function(key) {
return d.y[key];
});
})
])
.nice();
d3.select(".x--axis")
.transition()
.call(d3.axisBottom(x0).tickFormat(formatTime));
d3.select(".y--axis")
.transition()
.call(d3.axisLeft(y));
var barGroups = g
.select(".bars")
.selectAll(".barGroup")
.data(data);
barGroups
.enter()
.append("g")
.attr("transform", function(d) {
return "translate(" + x0(d.x) + ",0)";
})
.attr("class", "barGroup")
.selectAll("rect")
.data(function(d) {
return keys.map(function(key) {
return { key: key, value: d.y[key] };
});
})
.enter()
.append("rect")
.attr("x", function(d) {
return x1(d.key);
})
.attr("y", function(d) {
return y(d.value);
})
.attr("width", x1.bandwidth())
.attr("height", function(d) {
return height - y(d.value);
})
.attr("class", function(d) {
return "data-" + d.key.replace(/ /g, "");
})
.attr("fill", function(d) {
return z(d.key);
})
.merge(barGroups)
.attr("width", x1.bandwidth())
.attr("height", function(d) {
return height - y(d.value);
})
.attr("x", function(d) {
return x1(d.key);
})
.attr("y", function(d) {
return y(d.value);
});
// Exit
var old = barGroups
.exit()
.remove();
// Release memory for elements that were removed
old = null;
}
function generateData() {
var lastDate = new Date();
if (data.length > 0) {
lastDate = new Date(data[data.length - 1].x);
}
lastDate.setHours(lastDate.getHours() + 1);
data.push({
x: lastDate,
y: {
A: d3.randomUniform(0, 100)(),
B: d3.randomUniform(0, 100)(),
C: d3.randomUniform(0, 100)()
}
});
}
/* Based on https://bl.ocks.org/mbostock/3887051 */
rect.bar {
fill: steelblue;
}
text {
fill: #000;
font: 11px sans-serif;
font-weight:500;
}
/* body {
background-color: #f00;
} */
.legend rect:hover {
stroke-width:0.5;
stroke: black;
}
svg {
background-color:#eee;
shape-rendering: crispEdges;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>
<!-- Based on https://bl.ocks.org/mbostock/3887051 -->
<svg width="900" height="400"></svg>
答案 0 :(得分:0)
我提供的这种模式用于更新分组条形图。如果不深入研究代码,可能会对其进行调整。
//update pattern for bar chart
var groups = this.plot.selectAll('.bar-group').data(data, function(d) { return d; });
//EXIT bars no longer in the data
groups.exit()
.transition()
.duration(300)
.remove();
//ENTER bars with new data
var bars = groups.enter().append("g")
.attr('class', 'bar-group')
.attr("transform", function(d) { return "translate(" + that.x0Scale(d[that.x_var]) + ",0)"; })
.merge(groups)
.selectAll('rect')
.data(function(d) { return that.grouping.map(function(key) { return {key: key, value: +d[key]}; }); });
//EXIT bars in group just in case that changed
bars.exit().transition().duration(300).attr('height', 0).attr("y", that.yScale(0)).remove()
bars.enter().append("rect")
.attr('class', 'bar')
.attr("x", function(d) { return that.x1Scale(d.key); })
.attr("y", that.yScale(0));
.merge(bars)
.transition().duration(500)
.attr("x", function(d) { return that.x1Scale(d.key); })
.attr("y", function(d) { return that.yScale(Math.max(0, d.value)); })
.attr("width", d3.min([that.x1Scale.bandwidth(), 200]))
.attr("height", function(d) { return Math.abs(that.yScale(0)- that.yScale(d.value)); })
.attr("fill", function(d) { return that.zScale(d.key); })
.attr("opacity", 0.85 );