An example of setting x- and y-scale domains (zooming) by selecting a
rectangular region using the mouse. The original question required that it
work in tandem with d3.behavior.zoom
for panning, hence the checkbox for
switching on the “zoom by rectangle” mode.
-
-
Save xgrommx/8541fcf8a6dad3fa6a42 to your computer and use it in GitHub Desktop.
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> | |
<meta charset="utf-8"> | |
<title>Zoom by Rectangle</title> | |
<script src="http://d3js.org/d3.v2.min.js?2.10.1"></script> | |
<style> | |
body { | |
font-family: sans-serif; | |
} | |
.noselect { | |
-webkit-touch-callout: none; | |
-webkit-user-select: none; | |
-khtml-user-select: none; | |
-moz-user-select: none; | |
-ms-user-select: none; | |
user-select: none; | |
} | |
svg { | |
font: 10px sans-serif; | |
shape-rendering: crispEdges; | |
} | |
rect { | |
fill: #ddd; | |
} | |
rect.zoom { | |
stroke: steelblue; | |
fill-opacity: 0.5; | |
} | |
.axis path, .axis line { | |
fill: none; | |
stroke: #fff; | |
} | |
</style> | |
<p><label for="zoom-rect"><input type="checkbox" id="zoom-rect"> zoom by rectangle</label> | |
<script> | |
var margin = {top: 0, right: 12, bottom: 12, left: 36}, | |
width = 960 - margin.left - margin.right, | |
height = 430 - margin.top - margin.bottom; | |
var x = d3.scale.linear() | |
.domain([-width / 2, width / 2]) | |
.range([0, width]); | |
var y = d3.scale.linear() | |
.domain([-height / 2, height / 2]) | |
.range([height, 0]); | |
var xAxis = d3.svg.axis() | |
.scale(x) | |
.orient("bottom") | |
.tickSize(-height); | |
var yAxis = d3.svg.axis() | |
.scale(y) | |
.orient("left") | |
.ticks(5) | |
.tickSize(-width); | |
var zoom = d3.behavior.zoom().x(x).y(y).on("zoom", refresh); | |
var zoomRect = false; | |
d3.select("#zoom-rect").on("change", function() { | |
zoomRect = this.checked; | |
}); | |
var svg = d3.select("body").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 + ")") | |
.call(zoom) | |
.append("g") | |
.on("mousedown", function() { | |
if (!zoomRect) return; | |
var e = this, | |
origin = d3.mouse(e), | |
rect = svg.append("rect").attr("class", "zoom"); | |
d3.select("body").classed("noselect", true); | |
origin[0] = Math.max(0, Math.min(width, origin[0])); | |
origin[1] = Math.max(0, Math.min(height, origin[1])); | |
d3.select(window) | |
.on("mousemove.zoomRect", function() { | |
var m = d3.mouse(e); | |
m[0] = Math.max(0, Math.min(width, m[0])); | |
m[1] = Math.max(0, Math.min(height, m[1])); | |
rect.attr("x", Math.min(origin[0], m[0])) | |
.attr("y", Math.min(origin[1], m[1])) | |
.attr("width", Math.abs(m[0] - origin[0])) | |
.attr("height", Math.abs(m[1] - origin[1])); | |
}) | |
.on("mouseup.zoomRect", function() { | |
d3.select(window).on("mousemove.zoomRect", null).on("mouseup.zoomRect", null); | |
d3.select("body").classed("noselect", false); | |
var m = d3.mouse(e); | |
m[0] = Math.max(0, Math.min(width, m[0])); | |
m[1] = Math.max(0, Math.min(height, m[1])); | |
if (m[0] !== origin[0] && m[1] !== origin[1]) { | |
zoom.x(x.domain([origin[0], m[0]].map(x.invert).sort())) | |
.y(y.domain([origin[1], m[1]].map(y.invert).sort())); | |
} | |
rect.remove(); | |
refresh(); | |
}, true); | |
d3.event.stopPropagation(); | |
}); | |
svg.append("rect") | |
.attr("width", width) | |
.attr("height", height); | |
svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(xAxis); | |
svg.append("g") | |
.attr("class", "y axis") | |
.call(yAxis); | |
function refresh() { | |
svg.select(".x.axis").call(xAxis); | |
svg.select(".y.axis").call(yAxis); | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment