To zoom in, you just hold down the SHIFT key and draw a rectangle on the map using the mouse. The map then zooms to that extent. To zoom out again, hold down SHIFT and CONTROL and draw another rectangle.
So I got to thinking about what it would take to enable this functionality using the Google Maps API.
First, I needed a way to check which keys are being pressed at the time the map drawing occurs. The approach I used was to store any depressed keys in an array which I can then inspect when the user starts drawing on the map. If the SHIFT key is depressed, then my app needs to take notice, because the user plans to either zoom in (SHIFT + mouse draw), or zoom out (SHIFT + CTRL + mouse draw):
var keys = [];
onkeydown = onkeyup = function(e) {
e = e || event; // for IE
keys[e.keyCode] = e.type == 'keydown';
if (keys[16]) {
drawingManager.setMap(map);
} else {
drawingManager.setMap(null);
}
}
If the user has the SHIFT key depressed then they are about to draw an extent on the map, so I enable the Google Maps API DrawingManager. The drawing mode is set to RECTANGLE because a rectangle has a bounds property I can use for the new extent. I want everything to be keyboard-driven, so I hide the drawing control:
var drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.RECTANGLE,
drawingControl: false
});
When the user draws on the map, we want to see if either the SHIFT key (keyCode=16) and/or the CTRL key are pressed. (I got the key codes from this handy site.)
If the user is zooming in, then we get the bounds of the rectangle they have drawn on the map and call the map's fitBounds() method to zoom to that extent:
google.maps.event.addListener(drawingManager, "rectanglecomplete", function(rect) {
// user zooming in
if (keys[16]) {
map.fitBounds(rect.bounds);
rect.setMap(null);
return;
}
});
But what to do about zooming out? To be honest, I'm not 100% sure how Esri implement this, but for my purposes it's good enough just to recenter the map at the center of the rectangle the user has drawn and then zoom out one level:
google.maps.event.addListener(drawingManager,"rectanglecomplete", function(rect) {
// user zooming out
if (keys[16] || keys[17]) {
map.setCenter(rect.getBounds().getCenter());
var zoom = map.getZoom();
map.setZoom(--zoom);
rect.setMap(null);
return;
}
// user zooming in
if (keys[16]) {
map.fitBounds(rect.bounds);
rect.setMap(null);
return;
}
});
I check for the user zooming out first (i.e. CTRL (keycode=17) is pressed in addition to SHIFT (keycode=16)), so I can drop to the next test (SHIFT only) if CTRL is not depressed.
You can see the JS Fiddle for it here.
And that's about it. It's not perfect, and I'd want to do a bit more to it if I was using it in a production app, but it's a workable solution. If I'm unhappy about anything it's the zooming out behavior. Could I zoom out based on the size of the extent, perhaps? How would you implement this? Let me know in the comments!
No comments:
Post a Comment