|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<!-- this version adds and removes the diagram in the open box --> |
|
<meta charset="utf-8"> |
|
<script src="http://d3js.org/d3.v3.min.js"></script> |
|
<style> |
|
|
|
body { |
|
font: 10px sans-serif; |
|
margin: 0; |
|
} |
|
|
|
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"); |
|
|
|
// 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"); |
|
|
|
// set an event handler on each box |
|
var boxEnter = d3.selectAll("#boxes > g") |
|
.attr("class", function(d) { return d.status; }) |
|
.on('click', function(d) { togglebox(); update(); }); |
|
|
|
// make the outline of each 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; }) |
|
.each(function(d) { (openbox === d.id) ? add_diagram(d) : {} ; }); |
|
|
|
// 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."); |
|
|
|
// layout box outline extremity points |
|
function boxLayout(index) { |
|
|
|
var b, |
|
bl = [], |
|
bx = margin; |
|
|
|
for (var i=0; i<4; i++) { |
|
b = {}; |
|
b.id = i; |
|
b.x0 = b.x3 = bx; |
|
b.x1 = b.x2 = (i === index) ? bx + openboxwidth : bx + boxwidth; |
|
b.y0 = b.y1 = margin; |
|
b.y2 = b.y3 = margin + 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() { |
|
|
|
// identify the open box |
|
d3.selectAll("#boxes").select(".open").each(function(d) { openbox = d.id; }); |
|
|
|
// remake the layout with the new open box |
|
var boxes = boxLayout(openbox); |
|
|
|
// select the boxes and assign the new layout to them |
|
var boxUpdate = d3.selectAll("#boxes > g") |
|
.data(boxes, function(d) { return d.id; }); |
|
|
|
// update the box outlines |
|
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'; |
|
}); |
|
|
|
// remove diagram from previously open box |
|
remove_diagram(); |
|
|
|
// add diagram to the new open box |
|
boxUpdate.each(function(d) { (openbox === d.id) ? add_diagram(d) : {} ; }); |
|
|
|
// expose the open box contents gradually |
|
boxUpdate.select("g.drawing") |
|
.transition() |
|
.duration(750) |
|
.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"); |
|
} |
|
|
|
function add_diagram(d) { |
|
d3.selectAll("#boxes").select("g.open").select("g.drawing") |
|
.append("circle") |
|
.attr("fill", function(d) { return color[d.id]; }) |
|
.attr("r", boxwidth) |
|
.attr("cx", function (d) { return (d.x0 + d.x1)/2; }) |
|
.attr("cy", function (d) { return d.y0 + boxheight/2; }); |
|
} |
|
|
|
function remove_diagram() { |
|
d3.selectAll("#boxes").select("g.drawing > circle") |
|
.remove(); |
|
} |
|
|
|
</script> |
|
</body> |
|
</html> |