Skip to content

Instantly share code, notes, and snippets.

@StewartNoyce
Last active August 29, 2015 13:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StewartNoyce/9457213 to your computer and use it in GitHub Desktop.
Save StewartNoyce/9457213 to your computer and use it in GitHub Desktop.
Box Transition Lesson

This example shows the use of the d3 transition library, particularly with regards to timing. Four boxes are displayed, each containing a circle of a different color. One of them is open and the others are closed. Click on a box to open it.

Three separate transitions are initiated on three different element selections. Yet, the box outline and circle opacity transitions start after the box position transitions.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v3.min.js"></script>
<style>
body {
font: 10px sans-serif;
}
path {
fill: #fff;
stroke: #555;
}
text {
font-size: 14px;
}
</style>
</head>
<body>
<script type="text/javascript">
var width = 960,
height = 500;
var boxes = [],
boxwidth = 40,
openboxwidth = 180,
boxheight = 180,
margin = 40,
openbox = 0;
color = [ "#d7191c", "#e66101", "#1a9641", "#2b83ba" ];
// place boxes at the top left margin
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("id", "boxes")
.attr("transform", "translate(40, 40)");
// compute the initial layout using global coordinates, and an open box index
var boxes = boxLayout(openbox);
// make the boxes
d3.select("#boxes").selectAll("g").data(boxes).enter().append("g");
// translate the box to a starting point in the layout
var boxEnter = d3.selectAll("#boxes > g")
.attr("class", function(d) { return d.status; })
.attr("transform", function(d) { return "translate("+d.t+",0)"; })
.on('click', function(d) { togglebox(); update(); });
// make the outline of the box as a path
boxEnter.append('g')
.attr("class", "outline")
.append("path")
.transition()
.duration(500)
.attr('d', function(d) {
return 'M '+d.x0+' '+d.y0+' L '+d.x1+' '+d.y1+' L '+d.x2+' '+d.y2+' L '+d.x3+' '+d.y3+' z';
});
// make a drawing inside the box
boxEnter.append("g")
.attr("class", "drawing")
.style("opacity", function(d) { return d.opacity; })
.append("circle")
.attr("fill", function(d) { return color[d.id]; })
.attr("r", boxwidth)
.attr("cx", openboxwidth/2)
.attr("cy", boxheight/2);
// tell visitors what to do with the boxes
d3.select("body > svg").append("text")
.attr("text-anchor", "left")
.attr("x", margin)
.attr("y", (2*margin + boxheight))
.text("Click on a box to open it.");
// create a new set of box transform and path extremity points
function boxLayout(index) {
var b,
bl = [],
bx = 0;
for (var i=0; i<4; i++) {
b = {};
b.id = i;
b.t = bx;
b.x0 = b.x3 = 0;
b.x1 = b.x2 = (i === index) ? openboxwidth : boxwidth;
b.y0 = b.y1 = 0;
b.y2 = b.y3 = boxheight;
b.opacity = (i === index) ? 1 : 0;
b.status = (i === index) ? 'open' : 'closed';
bl.push(b);
bx += (i === index) ? openboxwidth : boxwidth;
}
return bl;
}
function update() {
// set the openbox index
d3.selectAll("#boxes").select(".open").each(function(d) { openbox = d.id; });
// make the layout with the new openbox
var boxes = boxLayout(openbox);
// move the boxes into place
var boxUpdate = d3.selectAll("#boxes > g")
.data(boxes, function(d) { return d.id; })
.transition()
.duration(500)
.attr("transform", function(d) { return "translate("+d.t+",0)"; });
// update the box frames
boxUpdate.select("g.outline > path")
.transition()
.duration(500)
.attr('d', function(d) {
return 'M '+d.x0+' '+d.y0+' L '+d.x1+' '+d.y1+' L '+d.x2+' '+d.y2+' L '+d.x3+' '+d.y3+' z';
});
// update the drawing opacity (exposes the new openbox and hides the old)
boxUpdate.select("g.drawing")
.style("opacity", 0)
.transition()
.duration(1000)
.style("opacity", function(d) { return d.opacity; });
}
function togglebox() {
// close the open box
d3.select("#boxes").select(".open").attr("class", "closed");
// open the selected box
d3.select(d3.event.currentTarget).attr("class","open");
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment