Zooming is no more than changing the scale for our projection. Rotating is no more than changing the rotation values of our projection. When you want the user to mandate zoom and rotation, you will need to listen to their mouse movement. As such, you will need to set up a zoom listener to track the user's mouse wheel and drag moves, and attach it to the Canvas. We implemented zoom and rotation already in chapter 5, Click-Click Boom! Applying Interactivity to Your Map. In our ready() function, as specified above, we will use D3’s zoom behavior to deliver all the user interaction changes we need:
var zoom = d3.zoom()
.scaleExtent([0.5, 4])
.on("zoom", zoomed);
canvas.call(zoom);
function zoomed() { // our handler code goes here }
First, you create the zoom behavior with d3.zoom(), define scaling bounds between 0.5 and 4, and inform the behavior to trigger our zoomed() handler as soon as a “zoom” event has been triggered. However, so far, this has been a blunt tool. To understand what it does, you have to call it on an element. Call it on your Canvas element, and that element will be the sensor of all zoom-related user events. Importantly, it will listen for mouse wheel and drag events and expose the event information in the global d3.event object. It will further store the information in the base element it got called on (in our case, the main Canvas), but we’ll be happily served by the d3.event object you can tap into at each event.
Further, we want to set up some variables for tracking our scale and rotation whereabouts during zoom. We do this at the very top of our code with the following global variables:
var width = 960,
height = 600,
projectionScale = origProjectionScale = height / 2.1,
translation = [width / 2, height / 2],
projectionScaleChange,
prevTransformScale = 1,
rotation;
The newcomers in the preceding code are origProjectionScale, projectionScaleChange, prevTransformScale, and rotation. Their mission will become clear in the following paragraphs.