Another no SVG piece that extends the earlier example. In this case, the zoomed image has a border so that users aren’t confused about the transparent parts of a PNG image not responding to a mouseout event. It also includes a select element populated by the same data array that was used to build the gallery and which lets you zoom to the row containing the image you select.
<html xmlns="//www.w3.org/1999/xhtml">
<head>
<title>D3 in Action Gallery Example 2</title>
<meta charset="utf-8" />
</head>
<script src="//d3js.org/d3.v3.min.js" type="text/javascript"></script>
<script src="//d3js.org/colorbrewer.v1.min.js"></script>
<style>
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 onload="galleryExample2()">
<div id="controls">
</div>
</body>
<footer>
<script>
function galleryExample2() {
imageArray = [];
d3.select("#controls").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, data: dataURL});
}
d3.select("canvas").remove();
d3.select("#controls")
.append("div").attr("class", "gallery")
.selectAll("img").data(imageArray).enter().append("img")
.attr("class", "infinite")
.attr("src", function(d) {return d.data})
.on("mouseover", highlightImage)
.on("mouseout", dehighlightImage)
redrawGallery();
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 redrawGallery() {
var newHeight = parseFloat(d3.select("div.gallery").node().clientHeight);
var newWidth = parseFloat(d3.select("div.gallery").node().clientWidth);
var imageSize = newWidth / 8;
d3.selectAll("img")
.style("width", newWidth / 8)
.style("top", function(d) {return Math.floor(d.x / 8) * imageSize})
.style("left", function(d) {return d.x%8 * imageSize})
}
window.onresize = function(event) {
redrawGallery();
}
d3.select("div.gallery").style("height", "50%").style("overflow","scroll").style("border", "2px black solid")
d3.select("#controls").append("select")
//.attr("onchange", function (d) {return "zoomTo("+d.x+")"})
.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 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(scrollTop) {
return function() {
var i = d3.interpolateNumber(this.scrollTop, scrollTop);
return function(t) { this.scrollTop = i(t); };
};
}
}
}
</script>
</footer>
</html>