Skip to content

Instantly share code, notes, and snippets.

@emeeks
Last active March 17, 2016 16:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emeeks/be3879c20a79646cc6ef to your computer and use it in GitHub Desktop.
Save emeeks/be3879c20a79646cc6ef to your computer and use it in GitHub Desktop.
Ch. 8, Fig. 11 - D3.js in Action

This is the code for Chapter 8, Figure 11 from D3.js in Action that creates an image gallery with a zoom-to-image select input. This example uses D3 not only to create the image gallery made up of img elements but also the option elements that make the select input function.

<html>
<head>
<title>D3 in Action Chapter 8 - Example 9</title>
<meta charset="utf-8" />
<script src="https://d3js.org/colorbrewer.v1.min.js" type="text/JavaScript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
</head>
<style>
tr {
border: 1px gray solid;
}
td {
border: 2px black solid;
}
div.table {
position:relative;
}
div.data {
position: absolute;
width: 90px;
padding: 0 5px;
}
div.head {
position: absolute;
}
div.datarow {
position: absolute;
width: 100%;
border-top: 2px black solid;
background: white;
height: 35px;
overflow: hidden;
}
div.gallery {
position: relative;
}
img.infinite {
position: absolute;
background: rgba(255,255,255,0);
border-width: 1px;
border-style: solid;
border-color: rgba(0,0,0,0);
}
</style>
<body>
<div id="traditional">
</div>
</body>
<footer>
<script>
imageArray = [];
d3.select("#traditional").append("canvas").attr("height", 500).attr("width", 500);
var context = d3.select("canvas").node().getContext("2d");
context.textAlign = "center";
context.font="200px Georgia";
colorScale = d3.scale.quantize().domain([0,1]).range(colorbrewer.Reds[7]);
lineScale = d3.scale.quantize().domain([0,1]).range([10,40]);
for (var x=0;x<100;x++) {
context.clearRect(0,0,500,500);
context.strokeStyle = colorScale(Math.random());
context.lineWidth = lineScale(Math.random());
context.fillStyle = colorScale(Math.random());
context.beginPath();
context.arc(250,250,200,0,2*Math.PI);
context.fill();
context.stroke();
context.fillStyle = "black";
context.fillText(x,250,280);
var dataURL = d3.select("canvas").node().toDataURL();
imageArray.push({x: x, url: dataURL});
}
imgPerLine = 8;
d3.select("canvas").remove();
d3.select("#traditional")
.append("div").attr("class", "gallery")
.selectAll("img").data(imageArray).enter().append("img")
.attr("class", "infinite")
.attr("src", function(d) {return d.url})
redrawGallery();
d3.selectAll("img")
.on("mouseover", highlightImage)
.on("mouseout", dehighlightImage)
d3.select("div.gallery").style("height", "50%").style("overflow","scroll").style("border", "2px black solid")
d3.select("#traditional").append("select")
.on("change", zoomTo)
.selectAll("option").data(d3.selectAll("img").data()).enter().append("option").attr("value", function(d) {return d.x}).html(function(d) {return "Image #" +d.x})
function redrawGallery() {
var newWidth = parseFloat(d3.select("div.gallery").node().clientWidth);
var imageSize = newWidth / imgPerLine;
function imgX(x) {
return Math.floor(x / imgPerLine) * imageSize;
}
function imgY(x) {
return Math.floor(x%imgPerLine * imageSize)
}
d3.selectAll("img")
.style("width", newWidth / imgPerLine)
.style("top", function(d) {return imgX(d.x)})
.style("left", function(d) {return imgY(d.x)})
}
function highlightImage(d) {
var newWidth = parseFloat(d3.select("div.gallery").node().clientWidth);
var imageSize = newWidth / 8;
d3.select(this).transition().duration(500).style("width", imageSize * 2)
.style("background", "rgba(255,255,255,1)")
.style("border-color", "rgba(0,0,0,1)");
this.parentNode.appendChild(this)
}
function dehighlightImage(d) {
var newWidth = parseFloat(d3.select("div.gallery").node().clientWidth);
var imageSize = newWidth / 8;
d3.select(this).transition().duration(500).style("width", imageSize)
.style("background", "rgba(255,255,255,0)")
.style("border-color", "rgba(0,0,0,0)")
}
function zoomTo() {
var selectValue = d3.select("select").node().value;
var newWidth = parseFloat(d3.select("div.gallery").node().clientWidth);
var imageSize = newWidth / 8;
var scrollTarget = Math.floor(selectValue / 8) * imageSize;
d3.selectAll("img").filter(function(d) {return d.x == selectValue})
.transition().duration(2000).style("width", imageSize * 2)
.style("background", "rgba(255,255,255,1)")
.style("border-color", "rgba(0,0,0,1)");
var selectedNode = d3.selectAll("img")
.filter(function(d) {return d.x == selectValue}).node();
selectedNode.parentNode.appendChild(selectedNode);
d3.select("div.gallery").transition().duration(2000)
.tween("scrollTween", scrollTopTween(scrollTarget));
function scrollTopTween(scrollTo) {
return function() {
var i = d3.interpolateNumber(this.scrollTop, scrollTo);
return function(t) { this.scrollTop = i(t); };
};
}
}
window.onresize = function(event) {
redrawGallery();
}
</script>
</footer>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment