Click anywhere on the background to pan. Move the triangle to zoom.
Created
October 8, 2012 09:36
-
-
Save j-mueller/3851650 to your computer and use it in GitHub Desktop.
Zoom and Pan with D3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.zoomchart div { | |
width: 100%; | |
} | |
.axis path, .axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.axis text { | |
font: 12px sans-serif; | |
font-family: 'Segoe UI', sans-serif; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | |
<title>Zoom and Pan with D3</title> | |
<meta name="description" content="Zoom with D3"> | |
<meta name="viewport" content="width=device-width"> | |
<link rel="stylesheet" href="chart.css"> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> | |
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?2.5.0"></script> | |
</head> | |
<body> | |
<div class="zoomchart" id="zoomChart"> | |
</div> | |
<script type="text/javascript" src="zoom.js"></script> | |
<script type="text/javascript"> | |
var width = $('#zoomChart').width(), | |
z = zoom().width(width).height(300); | |
zoomChart = d3.select(".zoomchart"); | |
zoomChart.call(z); | |
zoomChart.select(".viewport") | |
.append("rect") | |
.attr("x", 100) | |
.attr("y", 100) | |
.attr("width", 60) | |
.attr("height", 40) | |
.attr("fill", "#555"); | |
zoomChart.select(".viewport") | |
.append("rect") | |
.attr("x", 200) | |
.attr("y", 150) | |
.attr("width", 60) | |
.attr("height", 40) | |
.attr("fill", "#922"); | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//A zoom widget for d3 | |
function zoom() { | |
var margin = {top: 10, right: 40, bottom: 150, left: 60}, | |
width = 940 - margin.left - margin.right, | |
height = 1024 - margin.top - margin.bottom | |
changeZoom = function() {}; | |
function chart(div) { | |
div.each(function() { | |
var div = d3.select(this), | |
svg = div.select("svg"), | |
zoomer = svg.select(".zoomer"), | |
viewport = svg.select(".viewport"), | |
pan = svg.select(".pan"), | |
yOffset = 0, | |
xOffset = 20, | |
zoomlevel = 100; | |
var viewportTranslation = function() { | |
return "translate(" + xOffset + "," + yOffset + ")"; | |
} | |
var viewportScale = function() { | |
return "scale(" + 0.01 * zoomlevel + ")"; | |
} | |
var viewportTransform = function() { | |
return viewportTranslation() + "," + viewportScale(); | |
} | |
var applyZoomLevel = function() { | |
svg.select(".icon").attr("transform", "translate(0," + y(zoomlevel) + ")"); | |
svg.select(".viewport").attr("transform", viewportTransform); | |
} | |
changeZoom = function(d) { | |
zoomlevel = Math.min(500, Math.max(10, zoomlevel + d)); | |
applyZoomLevel(); | |
} | |
if (svg.empty()) { | |
svg = div.append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
pan = svg.append("g").attr("class", "pan"); | |
viewport = svg.append("g").attr("class", "viewport").attr("transform", viewportTransform()); //Translate to the right so that the pointer is not on the viewport | |
zoomer = svg.append("g").attr("class", "zoomer"); | |
//Create zoom thingy | |
var y = d3.scale.linear().domain([5, 500]).range([0, height]), | |
yAxis = d3.svg.axis() | |
.scale(y) | |
.orient("left"), | |
zoomerDrag = d3.behavior.drag().origin(function(d,i) { return {x : 0, y: y(zoomlevel)};}).on("drag", dragzoom), | |
zoomerPan = d3.behavior.drag().origin(function(d,i) { return {x: xOffset, y: yOffset }}).on("drag", dragPan); | |
zoomer.append("rect") | |
.attr("width", 20) | |
.attr("height", height) | |
.attr("fill", "#ddd") | |
.attr("fill-opacity", "0.8") | |
.on("click", function() { | |
var newY = Math.min(y(500) - 10, Math.max(y(5) - 10, d3.event.y - 25));//10 is the vertical coordinate of the arrow point | |
zoomlevel = y.invert(newY); | |
applyZoomLevel(); | |
}); | |
zoomer.append("g") | |
.attr("class", "y axis") | |
.call(yAxis); | |
//A simple triangle | |
var iconPath = "M 0,10 20,20 20,0 z"; | |
var iconGroup = zoomer.datum({}).append("g").attr("class", "icon") | |
.attr("mouse", "move"); | |
iconGroup.append("path") | |
.attr("class", "pointer") | |
.attr("d", iconPath) | |
.attr("fill", "#444"); | |
iconGroup | |
.attr("transform", "translate(0," + (y(zoomlevel) - 10) + ")") | |
.call(zoomerDrag); | |
pan.append("rect") | |
.attr("width", width) | |
.attr("height", height) | |
.attr("transform", "translate(20,0)") | |
.attr("fill", "#fff") | |
.call(zoomerPan); | |
function dragzoom(d) { | |
var newY = Math.min(y(500) - 10, Math.max(y(5) - 10, d3.event.y - 10));//10 is the vertical coordinate of the arrow point | |
zoomlevel = y.invert(newY); | |
applyZoomLevel(); | |
} | |
function dragPan(d) { | |
xOffset = d3.event.x; | |
yOffset = d3.event.y; | |
svg.select(".viewport").attr("transform", viewportTransform); | |
} | |
}; | |
}); | |
} | |
chart.height = function(h) { | |
if (!arguments.length) return h; | |
height = h; | |
return chart; | |
} | |
chart.width = function(w) { | |
if (!arguments.length) return w; | |
width = w; | |
return chart; | |
} | |
chart.zoom = function(d) { | |
changeZoom(d); | |
} | |
return chart; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment