Thursday, March 8, 2012

Zooming in with a window

I often get tired of using the scroll wheel to zoom, and get too lazy to move the mouse to the zoom slider. Here's an alternative to these zoom methods: define a zoom window to cover an area of interest.


Left-click to define a corner, let go, and move the mouse to draw the zoom window. Click again to zoom in. Right-click to cancel an open rectangle. Double right-click to zoom out (this behavior is standard).


In the definitions, I add a two helper functions to simplify the creation of LatLngs and LatLngBounds.

      var map;
      var mapOptions = {
        center: new google.maps.LatLng(0.0, 0.0),
        zoom: 2,
        mapTypeId: google.maps.MapTypeId.ROADMAP
      };
      var state = 0;
      var bounds;
      var pt1, pt2;
      var rect;


      function toLatLng(lat, lng) {
        return new google.maps.LatLng(lat, lng);
      }


      function toBounds(j,k) {
        var pts = [];
        var latMin, latMax, lngMin, lngMax;
        var sw, ne;


        latMin = Math.min(j.lat(), k.lat());
        latMax = Math.max(j.lat(), k.lat());


        lngMin = Math.min(j.lng(), k.lng());
        lngMax = Math.max(j.lng(), k.lng());


        sw = toLatLng(latMin, lngMin);
        ne = toLatLng(latMax, lngMax);
        return new google.maps.LatLngBounds(sw, ne);
      }


The initialize() function defines the map and the Rectangle's style. To minimize the effects of Internet Explorer's slow refresh, the size is fixed around (0,0). 


Next, a click listener on the map serves to place the first corner of the zoom window. The 'state' variable keeps track of whether the zoom window is open or not.

        google.maps.event.addListener(map, 'click', function(event) {
          if(state == 0) {
            pt1 = event.latLng;
            rect.setMap(map);
            state = 1;
          }
        });


With movement (mousemove), the Rectangle (zoom window) resizes according to the current position:

        google.maps.event.addListener(map, 'mousemove', function(event) {
          if(rect.getMap() == map) {
            rect.setBounds(toBounds(pt1, event.latLng));
          }
        });


Finally, if another click is detected (note that once the Rectangle is visible, it lies on top of the map) the Rectangle is hidden and the map is zoomed in.

        google.maps.event.addListener(rect, 'click', function(event) {
          rect.setMap(null);
          rect.setBounds(toBounds(toLatLng(0.0, 0.0), toLatLng(0.000001,0.000001)));
          pt2 = event.latLng;
          map.fitBounds(toBounds(pt1, pt2));
          state = 0;
        });


Finally, we add some behavior to correct the size of the zoom window. If movement is detected in the direction of the Rectangle, its size is reduced.



        // Allows shrinking the zoom window
        google.maps.event.addListener(rect, 'mousemove', function(event) {
          if(rect.getMap() == map) {
            rect.setBounds(toBounds(pt1, event.latLng));
          }
        });

and right-click closes an open Rectangle.

        // Cancel the zoom window with a left click
        google.maps.event.addListener(rect, 'rightclick', function(event) {
          rect.setMap(null);
          rect.setBounds(toBounds(toLatLng(0.0, 0.0), toLatLng(0.000001,0.000001)));
          state = 0;
        });


Full source code:

No comments:

Post a Comment