Customizing controls and overlapping maps

The goal of this recipe is to practice working with Google Maps. We will integrate what we learned about working with Google Maps in this chapter and incorporate our control over the user behaviors, such as what controllers the user can use, into it. We will start digging into creating our own unsupported undocumented behaviors, such as locking the users' pan area.

Our main task in this recipe will be to take our work from the previous recipe, and instead of having the map zoom in and move around, create clean transitions between the zoomed in and zoomed out options; but as that isn't supported in a clean way through the interface, we will use external focuses. The idea is simple; we will stack up two maps on top of each other and fade in and out the top map, giving us total control over the fluidity of the transitions.

Getting ready

Even though we are starting from scratch, a lot of the work that we did in the last recipe is being re-used, so I strongly encourage you to go through the last recipe Adding markers and events before moving into this one.

In this recipe, we will be integrating jQuery into our work as well, to save us time on creating our own animator tool (or re-using the one that we created in the Animating independent layers recipe in Chapter 6, Bringing Static Things to Life), as it would take us away from our main topic.

How to do it...

In this recipe we will be creating two files. An HTML file and a JS file. Let's look into it, starting with the HTML file:

  1. Create an HTML file and import the Google maps API and jQuery:
    <!DOCTYPE html>
    <html>
      <head>
        <title>Google Maps Markers and Events</title>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
        <script src="http://maps.googleapis.com/maps/api/js?key=AIzaSyAywwIFJPo67Yd4vZgPz4EUSVu10BLHroE&sensor=true"></script>
        <script src="./09.05.controls.js"></script>
      </head>
      <body onload="init();">
        <div id="mapIn"></div>
      <div id="mapOut"></div>
      </body>
    </html>
  2. Use CSS to stack the map's layers on top of each other:
    <style>
        html { height: 100% }
        body { height: 100%; margin: 0; padding: 0 }
        #mapIn, #mapOut { height: 100%; width:100%; position:absolute; top:0px; left:0px }
    </style>
  3. Create the 09.05.controls.js JS file and create an init function in it (from this point onwards the rest of the code will be in the init function):
    function init(){
      //rest of code in here
    }
  4. Create the two maps with their custom information:
    var BASE_CENTER = new google.maps.LatLng(40.7142,-74.0064 );
    
    //40.7142° N, -74.0064 E NYC
    var mapOut = new google.maps.Map(document.getElementById("mapOut"),{
      center: BASE_CENTER,
      zoom: 11,
      mapTypeId: google.maps.MapTypeId.SATELLITE,
      disableDefaultUI: true
    });
    var mapIn = new google.maps.Map(document.getElementById("mapIn"),{
      center: BASE_CENTER,
      zoom: 14,
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      disableDefaultUI: true,
      panControl:true
    });
  5. Add the markers to the upper layer map:
    var aMarkers = [
      {label:'New York City',
      local: mapOut.getCenter()},
      {label:'Brooklyn',
      local: new google.maps.LatLng(40.648, -73.957)},
      {label:'Queens',
      local: new google.maps.LatLng(40.732, -73.800)}, 
      {label:'Bronx',
      local: new google.maps.LatLng(40.851, -73.871)},  
    
    ];
    var marker;
    
      for(var i=0; i<aMarkers.length; i++){
        marker = new google.maps.Marker({
          position: aMarkers[i].local,
          map: mapOut,
          title: aMarkers[i].label
        });
    
      google.maps.event.addListener(marker, 'click', onMarkerClicked);
    
      }
    
      function onMarkerClicked(ev){
        mapIn.panTo(ev.latLng);
        $("#mapOut").fadeOut(1000);
      }
  6. Add the click event to the internal map, and when you have clicked on it, you will be returned to the upper map:
    google.maps.event.addListener(mapIn, 'click', function() {
      mapIn.panTo(BASE_CENTER);
      $("#mapOut").fadeIn(1000);
      });
  7. Force the user to disable pan in the upper map using the center_changed event:
    google.maps.event.addListener(mapOut, 'center_changed', function() {
            mapOut.panTo(BASE_CENTER); 
    //always force users back to center point in external map
    });

When you load the HTML file, you will find a fullscreen map that cannot be dragged. When you click on a marker, it will fade into the selected area. You can now drag the cursor around the map. The next time you click in the internal map (regular click on any area), the map will fade back to the original upper layer.

How it works...

Our biggest step is the creation of two maps, one overlapping the other. We did that with some CSS magic by layering the elements and putting our top layer at the last position in the stack (we could probably use the z-index to validate it, but it worked so I didn't add that to the CSS). After that we created our two div layers and set their CSS code. In the JavaScript code, contrary to the way we did in the last recipe, we hardcoded the values that we wanted into both the maps.

In our options for both the maps, we set the default controllers not to take effect by setting the property disableDefaultUI to be true, while in mapIn we set panControl to be true to showcase that the map can be panned through:

var mapOut = new google.maps.Map(document.getElementById("mapOut"),{
  center: BASE_CENTER,
  zoom: 11,
  mapTypeId: google.maps.MapTypeId.SATELLITE,
  disableDefaultUI: true
});
var mapIn = new google.maps.Map(document.getElementById("mapIn"),{
  center: BASE_CENTER,
  zoom: 14,
  mapTypeId: google.maps.MapTypeId.ROADMAP,
  disableDefaultUI: true,
  panControl:true
});

We can manually set all the controllers by setting a Boolean value to any of the following options:

  • panControl
  • zoomControl
  • mapTypeControl
  • streetViewControl
  • overviewMapControl

Our event logic works in the exact same way that it did in the last recipe. The only change is within the actual listeners where we switch between the maps using jQuery:

function onMarkerClicked(ev){
  mapIn.panTo(ev.latLng);
  $("#mapOut").fadeOut(1000);
}

google.maps.event.addListener(mapIn, 'click', function() {
  mapIn.panTo(BASE_CENTER);
  $("#mapOut").fadeIn(1000);
});

In both the event for the markers and the click event of the map, we are using the fadeIn and fadeOut methods of jQuery to animate our external maps visibility.

There's more...

When you try to drag around the higher-level map (the first visible map), you will notice that the map cannot move—it's not pannable. Google API v3 doesn't support the capability to disable the panning, but it does support the capability to get updated every time the map center point changes.

As such we listen in to the following change:

google.maps.event.addListener(mapOut, 'center_changed', function() {
        mapOut.panTo(BASE_CENTER); 
});

All we are doing is that each time the map position changes, we force it back to its original position, making it impossible to move our map around.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.86.56