Explaining D3 data binding. In this example you can enter your own data to the general update pattern and see the elements that will fall on each of the three states (enter, update, exit).
forked from mbostock's block: General Update Pattern, III
Original Readme by mbostock
By adding transitions, we can more easily follow the elements as they are entered, updated and exited. Separate transitions are defined for each of the three states. To avoid repeating transition timing parameters for the enter, update, and exit selections, a top-level transition t sets the duration, and then subsequent transitions use selection.transition, passing in t to inherit timing:
var t = d3.transition()
.duration(750);
Want to read more? Try these tutorials:
See the D3 wiki for even more resources.
Previous: Key Functions
forked from mbostock's block: General Update Pattern, III
xxxxxxxxxx
<meta charset="utf-8">
<style>
text {
font: bold 32px monospace;
}
.set text {
font: 18px monospace;
}
.enter {
fill: green;
}
.update {
fill: #333;
}
.exit {
fill: brown;
}
input {
width: 280px;
font-size: 18pt;
}
.controlPanel {
float:left;
}
button {
font-size: 18pt;
}
</style>
<div class="controlPanel">
<h2>Enter your own data</h2>
<input id="data" type="text">
<br>
<button id="btnUpdate">Update</button>
<button id="btnRandom">Random</button>
<h3>Previous data:</h3>
<div id="previous"></div>
</div>
<svg width="580" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
g = svg.append("g").attr("transform", "translate(32," + (height / 4) + ")"),
gGroups = svg.append("g").attr("transform", "translate(32," + (height / 4 * 3) + ")")
;
function update(data) {
var t = d3.transition()
.duration(750);
// JOIN new data with old elements.
var text = g.selectAll("text")
.data(data, function(d) { return d; });
// EXIT old elements not present in new data.
text.exit()
.attr("class", "exit")
.transition(t)
.attr("y", 60)
.style("fill-opacity", 1e-6)
.remove();
// UPDATE old elements present in new data.
text.attr("class", "update")
.attr("y", 0)
.style("fill-opacity", 1)
.transition(t)
.attr("x", function(d, i) { return i * 18; });
// ENTER new elements present in new data.
text.enter().append("text")
.attr("class", "enter")
.attr("dy", ".35em")
.attr("y", -60)
.attr("x", function(d, i) { return i * 18; })
.style("fill-opacity", 1e-6)
.text(function(d) { return d; })
.transition(t)
.attr("y", 0)
.style("fill-opacity", 1);
updateSets(data, text);
}
// Visualize the enter, update and exit sets of the passed selection
function updateSets(data, sel) {
var getData = function(sel) {
return sel.nodes().map(function (d) { return d.__data__; });
};
var set = gGroups.selectAll(".set")
.data([getData(sel.enter()), //enter set (created)
getData(sel), //update set
getData(sel.exit()) //exit set (removed)
]);
var setEnter = set.enter()
.append("g")
.attr("class", "set");
setEnter
.append("text")
.attr("class", "setTitle")
.attr("x", width/6)
.text(function (_,i) {
return i===0 ? "Enter":
i===1 ? "Update":
"Exit";
});
setEnter
.merge(set)
.classed("enter", function (_,i) { return i===0; })
.classed("update", function (_,i) { return i===1; })
.classed("exit", function (_,i) { return i===2; })
.attr("transform", function (_, i) {
return "translate(" + ( i*width/3 ) + ",0)";
});
set.exit().remove();
var text = setEnter
.merge(set)
.selectAll(".letter")
.data(function (d) { return d; });
text.enter()
.append("text")
.attr("class", "letter")
.merge(text)
.attr("y", 32)
.attr("x", function (d,i) { return i*9; })
.text(function (d) {
return d;
});
text.exit().remove();
d3.select("#data")
.property("value", data.join(","));
d3.select("#previous")
.insert("p", ":first-child")
.text(data.join(","));
}
// The initial display.
update(alphabet);
d3.select("#btnRandom")
.on("click", function () {
update(d3.shuffle(alphabet)
.slice(0, Math.floor(Math.random() * 26))
.sort());
});
d3.select("#btnUpdate")
.on("click", function () {
var data;
try {
data = d3.select("#data").property("value").split(",").map(d=> d.trim());
} catch (Exception) {
alert("Please enter a comma separated list");
}
update(data);
});
</script>
https://d3js.org/d3.v4.min.js