It's the 15th anniversary of Google Maps Platform - Check out the latest news and announcements

Custom Overlays

  1. Introduction
  2. Add a custom overlay
    1. Subclass the overlay
    2. Initialize the overlay
    3. Draw the overlay
  3. Remove a custom overlay
  4. Hide and show a custom overlay


Overlays are objects on the map that are tied to latitude/longitude coordinates, so they move when you drag or zoom the map. For information on predefined overlay types, see Drawing on the map.

The Maps JavaScript API provides an OverlayView class for creating your own custom overlays. The OverlayView is a base class that provides several methods you must implement when creating your overlays. The class also provides a few methods that make it possible to translate between screen coordinates and locations on the map.

Add a custom overlay

Here is a summary of the steps required to create a custom overlay:

  • Set your custom overlay object's prototype to a new instance of google.maps.OverlayView(). In effect, this will subclass the overlay class.
  • Create a constructor for your custom overlay, and set any initialization parameters.
  • Implement an onAdd() method within your prototype, and attach the overlay to the map. OverlayView.onAdd() will be called when the map is ready for the overlay to be attached.
  • Implement a draw() method within your prototype, and handle the visual display of your object. OverlayView.draw() will be called when the object is first displayed.
  • You should also implement an onRemove() method to clean up any elements you added within the overlay.

Below are more details on each step. You can also see the full, working example: view example.

Subclass the overlay

The example below uses OverlayView to create a simple image overlay.

// This example creates a custom overlay called USGSOverlay, containing
// a U.S. Geological Survey (USGS) image of the relevant area on the map.

// Set the custom overlay object's prototype to a new instance
// of OverlayView. In effect, this will subclass the overlay class therefore
// it's simpler to load the API synchronously, using
// google.maps.event.addDomListener().
// Note that we set the prototype to an instance, rather than the
// parent class itself, because we do not wish to modify the parent class.

var overlay;
USGSOverlay.prototype = new google.maps.OverlayView();

// Initialize the map and the custom overlay.

function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 11,
    center: {lat: 62.323907, lng: -150.109291},
    mapTypeId: 'satellite'

  var bounds = new google.maps.LatLngBounds(
      new google.maps.LatLng(62.281819, -150.287132),
      new google.maps.LatLng(62.400471, -150.005608));

  // The photograph is courtesy of the U.S. Geological Survey.
  var srcImage = '' +

  // The custom USGSOverlay object contains the USGS image,
  // the bounds of the image, and a reference to the map.
  overlay = new USGSOverlay(bounds, srcImage, map);

Now we create a constructor for the USGSOverlay class, and initialize the passed parameters as properties of the new object.

/** @constructor */
function USGSOverlay(bounds, image, map) {

  // Initialize all properties.
  this.bounds_ = bounds;
  this.image_ = image;
  this.map_ = map;

  // Define a property to hold the image's div. We'll
  // actually create this div upon receipt of the onAdd()
  // method so we'll leave it null for now.
  this.div_ = null;

  // Explicitly call setMap on this overlay.

We can't yet attach this overlay to the map in the overlay's constructor. First, we need to ensure that all of the map's panes are available, because they specify the order in which objects are displayed on a map. The API provides a helper method indicating this has occurred. We'll handle that method in the next section.

Initialize the overlay

When the overlay is first instantiated and ready to display, we need to attach it to the map via the browser's DOM. The API indicates that the overlay has been added to the map by invoking the overlay's onAdd() method. To handle this method we create a <div> to hold our image, add an <img> element, attach it to the <div>, and then attach the overlay to one of the map's panes. A pane is a node within the DOM tree.

The panes, of type MapPanes, specify the stacking order for different layers on the map. The following panes are available, and are enumerated in the order in which they are stacked from bottom to top:

  • mapPane is the lowest pane and is above the tiles. It may not receive DOM events. (Pane 0).
  • overlayLayer contains polylines, polygons, ground overlays and tile layer overlays. It may not receive DOM events. (Pane 1).
  • markerLayer contains markers. It may not receive DOM events. (Pane 2).
  • overlayMouseTarget contains elements that receive DOM events. (Pane 3).
  • floatPane contains the info window. It is above all map overlays. (Pane 4).

Because our image is a "ground overlay," we'll use the overlayLayer pane. When we have that pane, we'll attach our object to it as a child.

 * onAdd is called when the map's panes are ready and the overlay has been
 * added to the map.
USGSOverlay.prototype.onAdd = function() {

  var div = document.createElement('div'); = 'none'; = '0px'; = 'absolute';

  // Create the img element and attach it to the div.
  var img = document.createElement('img');
  img.src = this.image_; = '100%'; = '100%'; = 'absolute';

  this.div_ = div;

  // Add the element to the "overlayLayer" pane.
  var panes = this.getPanes();

Draw the overlay

Note that we haven't invoked any special visual display in the code above. The API invokes a separate draw() method on the overlay whenever it needs to draw the overlay on the map, including when first added.

We'll therefore implement this draw() method, retrieve the overlay's MapCanvasProjection using getProjection() and calculate the exact coordinates at which to anchor the object's top right and bottom left points. Then we can resize the <div>. In turn this will resize the image to match the bounds we specified in the overlay's constructor.

USGSOverlay.prototype.draw = function() {

  // We use the south-west and north-east
  // coordinates of the overlay to peg it to the correct position and size.
  // To do this, we need to retrieve the projection from the overlay.
  var overlayProjection = this.getProjection();

  // Retrieve the south-west and north-east coordinates of this overlay
  // in LatLngs and convert them to pixel coordinates.
  // We'll use these coordinates to resize the div.
  var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
  var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());

  // Resize the image's div to fit the indicated dimensions.
  var div = this.div_; = sw.x + 'px'; = ne.y + 'px'; = (ne.x - sw.x) + 'px'; = (sw.y - ne.y) + 'px';

Remove a custom overlay

We also add an onRemove() method to cleanly remove the overlay from the map.

// The onRemove() method will be called automatically from the API if
// we ever set the overlay's map property to 'null'.
USGSOverlay.prototype.onRemove = function() {
  this.div_ = null;

Hide and show a custom overlay

If you wish to hide or show an overlay rather than simply create or remove it, you can implement your own hide() and show() methods to adjust the overlay's visibility. Alternatively, you can detach the overlay from the map's DOM, though this operation is slightly more expensive. Note that if you then reattach the overlay to the map's DOM, it will re-invoke the overlay's onAdd() method.

The following example adds hide() and show() methods to the overlay's prototype which toggle the visibility of the container <div>. Additionally, we add a toggleDOM() method, which attaches or detaches the overlay to/from the map.

// Set the visibility to 'hidden' or 'visible'.
USGSOverlay.prototype.hide = function() {
  if (this.div_) {
    // The visibility property must be a string enclosed in quotes. = 'hidden';
}; = function() {
  if (this.div_) { = 'visible';

USGSOverlay.prototype.toggle = function() {
  if (this.div_) {
    if ( === 'hidden') {;
    } else {

// Detach the map from the DOM via toggleDOM().
// Note that if we later reattach the map, it will be visible again,
// because the containing <div> is recreated in the overlay's onAdd() method.
USGSOverlay.prototype.toggleDOM = function() {
  if (this.getMap()) {
    // Note: setMap(null) calls OverlayView.onRemove()
  } else {

Take care of the user interface:

<!-- Add an input button to initiate the toggle method on the overlay. -->
    <div id="floating-panel">
      <input type="button" value="Toggle visibility" onclick="overlay.toggle();"></input>
      <input type="button" value="Toggle DOM attachment" onclick="overlay.toggleDOM();"></input>

View example.