Google Maps Overlay

Gani / January 04, 2019

One of the web applications we are working on here in Bootyard is a rental platform where users can lend and rent items online.


The platform has many features that make rental transactions easy online. Some of the features are pages where the user uploaded pictures and details of items can be categorically viewed, via categorised pages, and also be searched via a page with a search form. 


The pages where you can see the uploaded items have a portion for a map, where actual locations of the items can be seen. Item locations are set by the users, or lenders, when they added details about the for rent item. The item locations, which are based on latitude and longitude, are represented by icons in the map.


The map is implemented using Google Maps API and the listing locations are attached to Google Map markers. For easier Google Maps API usage we are using a javascript library called `gmaps.js`.

Here is a screenshot of how the icons are shown in the map.
preview

Listing locations represented by custom Google Map marker icons.

The default icon for a map marker is a red dropper. You can customise the icon by specifying an image url into it's `icon` option, that is how we achieved that implementation above.

Task

I was tasked to update the map's appearance and meet some new map requirements.


Below is a screenshot of the expected output.
Expected Output

Desired map implementation.

So, looking at the picture, there are multiple things we need to do.

  1. Replace the map marker icons with brown circles.
  2. The numbers on the circle markers suggests that the markers should reflect how many items are listed on a same location.
  3. The markers with the `H` on them suggests a location where only one item is present.
  4. Notice the pale `H` icon on the upper-right. That indicates that the user's cursor is hovered on the listing it represent. Let's call it an active marker.

Implementation

Customised Google Map marker icons is not a good idea for this task because, since it uses images, you will have to create an image for all the possible number of items that would be needed by the map.


Google Map Overlay

Introducing Google Map Overlay. Reading the documentation, overlays can somehow be used similarly to markers. Like markers, overlays positions in the map are also defined by coordinates of latitude and longitude. 

The best thing for our task, we can define html elements and html element designs upon creation of an overlay. Now we can easily achieve the circle shape, brown colour, and set dynamically set the caption on the shape, in our case, a number or an `H`.

Here is the actual implementation:

Remove the flag icons from the marker.

Since we no longer need the custom marker icon image. We will set the icon url option to blank("") when we add a marker to the map:

map.addMarker({
    lat: lat,
    lng: lng,
    title: item_name,
    id: id,
    icon: { url: "", scaledSize: new google.maps.Size(30, 30), anchor: new google.maps.Point(15, 15) },
    infoWindow: {
      content: `Sample content`,
      maxWidth: 200
    }
});


Add the overlays.

Now for adding the overlays. Here is a function that handles it.

function(map, listingMarkers) {
  var listings = JSON.parse(listingMarkers);
  var matcher = listings
  listings.forEach(function(listing, index) {
    if (listing.lat != null && listing.lng != null) {
      var sameAddresses = [], sameAddressCounter = 0, markerContent = 'H', markerClass = 'marker';

      listings.forEach(function(l, i){
        if((l.lat == listing.lat) && (l.lng == listing.lng)){
          sameAddressCounter++;
          sameAddresses.push(l);
        }
      });
      
      if(sameAddressCounter > 1){ 
        markerContent = sameAddressCounter; 
        markerClass = 'marker marker-number';
      }

      map = addListingMarkers(map, sameAddresses);
      map.drawOverlay({
        lat: listing.lat,
        lng: listing.lng,
        title: listing.item_name,
        verticalAlign: 'middle',
        horizontalAlign: 'middle',
        content: `<div class='${markerClass} overlay-${listing.id}'><span>${markerContent}</span></div>`,
        id: listing.id
      })

    }
  });
 
  return map;
}

I will try to explain this code below.

We get to define how many items are present in the same location as the current item in the iteration in this part of the function:

      listings.forEach(function(l, i){
        if((l.lat == listing.lat) && (l.lng == listing.lng)){
          sameAddressCounter++;
          sameAddresses.push(l);
        }
      });


Overlays can be designed in your css files using classes or ids, so all I have to do is set or identify which element class we should add to the current overlay html content here:
      if(sameAddressCounter > 1){ 
        markerContent = sameAddressCounter; 
        markerClass = 'marker marker-number';
      }


Finally, after defining what needs to be defined, the actual drawing or creation of the overlay in this part of the code:
      map = addListingMarkers(map, sameAddresses);
      map.drawOverlay({
        lat: listing.lat,
        lng: listing.lng,
        title: listing.item_name,
        verticalAlign: 'middle',
        horizontalAlign: 'middle',
        content: `<div class='${markerClass} overlay-${listing.id}'><span>${markerContent}</span></div>`,
        id: listing.id
      })


The Active Marker

I defined the active overlay like this. When the user hovers on an item on the page, as items are bound to coordinates, you just pass the coordinates of the hovered item via a javascript event into the map. Then create another layer of overlay on that location in the map that has a class with css designs that would make it stand out from the rest of the map overlays.

Here is the code:

  map.drawOverlay({
    lat: lat,
    lng: lng,
    title: item_name,
    verticalAlign: 'middle',
    horizontalAlign: 'middle',
    content: `
     <div class='marker marker-active'><span></span></div>
    `,
    id: Id
  })


Conclusion

What we actually did here in this implementation was use overlays as replacement for the marker icons. One of the many pros, since overlays are html elements, they load faster than images.

So if you want to implement dynamic marker icons for your Google Map, take a look at Google Map overlays.