Skip to content

Instantly share code, notes, and snippets.

@mbostock
Last active February 9, 2016 02:02
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 mbostock/6140181 to your computer and use it in GitHub Desktop.
Save mbostock/6140181 to your computer and use it in GitHub Desktop.
No Zoom on Context Menu
license: gpl-3.0

You can selectively disable zooming by stopping the propagation of the mousedown event. Here, a mousedown listener restricts panning to left click, so that panning is not initiated when the context menu opens. (On OS X, the context menu also appears on control-mousedown, so this is prevented as well.)

The mousedown listener and zoom behavior are registered on the same element, so d3.event.stopImmmediatePropagation is needed to prevent the zoom behavior from hearing the mousedown event. Alternatively, you could use a capturing listener on a parent element, or a non-capturing listener on a child element.

On each mousedown, a small red pulse visually indicates that the event was stopped, while a green pulse indicates that the zoom behavior was triggered.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.axis line {
fill: none;
stroke: #ddd;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: -5, right: -5, bottom: -5, left: -5},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var zoom = d3.behavior.zoom()
.scaleExtent([1, 10])
.on("zoom", zoomed);
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.right + ")")
.on("mousedown", mousedowned)
.call(zoom);
svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all");
var container = svg.append("g");
container.append("g")
.attr("class", "axis axis--x")
.selectAll("line")
.data(d3.range(20.5, width - 10, 10))
.enter().append("line")
.attr("x1", function(d) { return d; })
.attr("y1", 20.5)
.attr("x2", function(d) { return d; })
.attr("y2", height - 19.5);
container.append("g")
.attr("class", "axis axis--y")
.selectAll("line")
.data(d3.range(20.5, height - 10, 10))
.enter().append("line")
.attr("x1", 20.5)
.attr("y1", function(d) { return d; })
.attr("x2", width - 19.5)
.attr("y2", function(d) { return d; });
function zoomed() {
container.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
function mousedowned() {
var stop = d3.event.button || d3.event.ctrlKey;
if (stop) d3.event.stopImmediatePropagation(); // stop zoom
svg.append("circle")
.attr("transform", "translate(" + d3.mouse(this) + ")")
.attr("r", 1e-6)
.style("fill", "none")
.style("stroke", stop ? "red" : "green")
.style("stroke-width", "3px")
.style("stroke-opacity", 1)
.transition()
.ease(Math.sqrt)
.duration(500)
.attr("r", 12)
.style("stroke-opacity", 0);
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment