Skip to content

Instantly share code, notes, and snippets.

@mindrones
Last active Mar 11, 2016
Embed
What would you like to do?
Enabling and disabling zoom with a timer
license: gpl-3.0
scrolling: yes

If a web page contains a chart with a zoom behavior, there's an inconvenience: when you scroll the page, as soon as your mouse is over the chart the scroll wheel stops scrolling the document and starts zooming that chart.

To avoid this, you might activate the chart zoom after a certain amount of time the mouse entered the chart and disable the chart zoom when the mouse leaves the chart.

I find this a nice solution as the user has to express the intention to use the chart by keeping the mouse over it for a bit.

On a mobile device:

  • pinching outside of the rectangle zooms the page itself (not the viz);
  • clicking inside the rectangle area enables the zoom, then you'll be able to pinch the viz to zoom the circle.

This block originated from this discussion.

* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html,
body {
width: 100%;
height: 120%;
}
body {
position: relative;
}
p {
position: fixed;
top: 0;
left: 0;
padding: 1em;
margin: 0.5em;
}
svg {
margin-top: 8em;
margin-left: 1em;
border: 1px solid grey;
}
svg circle {
fill: palegreen;
stroke: lightgreen;
stroke-width: 3;
}
<html>
<head>
<title>Enabling and disabling zoom with a timer</title>
<script src="//d3js.org/d3.v3.min.js"></script>
<link href="index.css" rel="stylesheet">
</head>
<body>
<script src="index.js"></script>
</body>
</html>
/* geometry */
var size = {width: 500, height: 200};
var center = {x: size.width / 2 , y: size.height / 2};
var radius = 0.8 * Math.min(center.x, center.y);
/* timer */
var stop = true;
function startTimer() {
stop = false;
d3.timer(function(elapsed) {
var remaining = Math.max(0, (zoomDelay - elapsed) / 1000);
if (!stop) {
if (remaining > 0) {
messageRemainingTime(remaining)
} else {
enableZoom();
messageZoomEnabled();
}
}
return stop || remaining === 0
})
}
function stopTimer() {
stop = true;
}
/* zooming */
var zoomDelay = 800;
var zoom =
d3.behavior.zoom()
.size([size.width, size.height])
.center([center.x, center.y])
.on('zoom', updateZoom);
function updateZoom() {
circle.attr('r', radius * zoom.scale())
}
function enableZoom() {
svg.call(zoom);
}
function disableZoom() {
svg.on('.zoom', null);
}
/* message */
function messageInit() {
p.text('hover the viz to enable zooming in ' + zoomDelay / 1000 + ' seconds');
}
function messageRemainingTime(t) {
p.text('zoom enabled in ' + t.toFixed(1) + ' seconds');
}
function messageZoomEnabled() {
p.text('zoom enabled');
}
/* DOM setup */
var p = d3.select('body').append('p')
var svg = d3.select('body').append('svg')
.attr('width', size.width)
.attr('height', size.height)
.on('mouseenter', function() {
startTimer()
})
.on('mouseleave', function() {
disableZoom()
stopTimer()
messageInit();
})
;
var circle = svg.append('circle')
.attr('cx', center.x)
.attr('cy', center.y)
.attr('r', radius)
messageInit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment