• JavaScript
  • HTML
 * This example overlays a historical map of Berlin
 * from 1789 on top of the base map.
 * @param {H.Map} map A HERE Map instance within the application
function overlayHistoricalBerlin(map) {
  // Create a tile provider from our images of historical Berlin
  var tileProvider = new H.map.provider.ImageTileProvider({
    // We have tiles only for zoom levels 12–15,
    // so on all other zoom levels only base map will be visible
    min: 12,
    max: 15,
    opacity: 0.5,
    getURL: function (column, row, zoom) {
      // If Berlin is not displayed, return a blank tile.
      if (((zoom == 12) && (row != 1343 || column != 2200)) ||
        ((zoom == 13) &&  (row < 2686 || column < 4400 || row > 2687 || column > 4401)) ||
        ((zoom == 14) && (row < 5372 || column < 8800 || row > 5375 || column > 8803)) ||
        ((zoom  == 15) && (row < 10744 || column < 17601 || row > 10750 || column > 17607))) {
        return 'https://heremaps.github.io/maps-api-for-javascript-examples/custom-tile-overlay/tiles/blank.png';
      } else {
        // The Old Berlin Map Tiler follows the TMS URL specification.
        // By specification, tiles should be accessible in the following format:
        // http://server_address/zoom_level/x/y.png
        return 'https://heremaps.github.io/maps-api-for-javascript-examples/custom-tile-overlay/tiles/'+ zoom+ '/'+ row + '/'+ column+ '.png';
  // Unless you own the map tile source,
  // you need to comply with the licensing agreement of the map tile provider.
  // Often this means giving attribution or copyright acknowledgment to the owner,
  // even if the tiles are offered free of charge.
  tileProvider.getCopyrights = function (bounds, level) {
    // We should return an array of objects that implement H.map.ICopyright interface
    return [{
      label: "Overlay derived from WikiMedia Commons",
      alt: 'Overlay Based on a WikiMedia Commons Image in the Public Domain'
  // Now let's create a layer that will consume tiles from our provider
  var overlayLayer = new H.map.layer.TileLayer(tileProvider, {
    // Let's make it semi-transparent
    opacity: 0.5

  // Finally add our layer containing old Berlin to a map
 * Boilerplate map initialization code starts below:

// Step 1: initialize communication with the platform
// In your own code, replace variable window.apikey with your own apikey
var platform = new H.service.Platform({
  apikey: window.apikey,
  useHTTPS: true,
  useCIT: true
var defaultLayers = platform.createDefaultLayers();

// Step 2: initialize a map
var map = new H.Map(document.getElementById('map'), defaultLayers.vector.normal.map, {
  center: new H.geo.Point(52.515, 13.405),
  zoom: 14,
  pixelRatio: window.devicePixelRatio || 1
// add a resize listener to make sure that the map occupies the whole container
window.addEventListener('resize', () => map.getViewPort().resize());

// Step 3: make the map interactive
// mapEvents enables the event system
// behavior implements default interactions for pan/zoom (also on mobile touch environments)
var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));

// Step 4: create the default UI component, for displaying bubbles
var ui = H.ui.UI.createDefault(map, defaultLayers);

// Step 5: Main logic goes here
<!DOCTYPE html>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes">
    <meta http-equiv="Content-type" content="text/html;charset=UTF-8">
    <meta name="description" content="Display custom map tiles as an overlay">
    <title>Adding an Overlay to the Map</title>
    <link rel="stylesheet" type="text/css" href="https://js.api.here.com/v3/3.1/mapsjs-ui.css" />
    <script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-core.js"></script>
    <script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-service.js"></script>
    <script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-ui.js"></script>
    <script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js"></script>
    <link rel="stylesheet" type="text/css" href="../template.css" />
    <link rel="stylesheet" type="text/css" href="demo.css" />
    <script type="text/javascript" src='../test-credentials.js'></script>
  <script type="text/javascript" src='../js-examples-rendering-helpers/iframe-height.js'></script></head>
    <div class="page-header">
        <h1>Adding an Overlay to the Map</h1>
        <p>Display custom map tiles as an overlay</p>
    <p>This example displays a movable map initially centered on the historical centre of <b>Berlin</b> (<i>52.515, °N, 13.405°E</i>) with an overlay of a historical map from 1789 on top of the base map. A public domain image was used as a source, and split it into individual map tiles. Additional tiles are only downloaded when the zoom level or location changes.</p>
    <div id="map"></div>
      <span>Wikimedia Commons Images</span><br/>
        The tile source is based on <a href="https://commons.wikimedia.org/wiki/File%3AMap_de_berlin_1789_%28georeferenced%29.jpg">an image of Berlin in 1789</a> from Wikimedia.<br/>
        Images provided by Wikimedia Commons are under the copyright of their owners.<br/>
        However, almost all <a href="https://commons.wikimedia.org/wiki/Commons:Reusing_content_outside_Wikimedia">content hosted on Wikimedia Commons</a> may be freely reused subject to certain restrictions.<br/>
        The example uses the <a target="_blank" rel="nofollow" href="http://developer.here.com/javascript-apis/documentation/v3/maps/topics_api_nlp/h-map-provider-imagetileprovider.html"><code>H.map.provider.ImageTileProvider</code></a> class for fetching our custom tiles. The <code>getUrl()</code> method constructs the URL of the tile for the specified column/row/zoom position. The result is displayed on the map as an additional layer using an instance of the <a target="_blank" rel="nofollow" href="http://developer.here.com/javascript-apis/documentation/v3/maps/topics_api_nlp/h-map-layer-layer.html"><code>H.map.layer.TileLayer</code></a> class which has been created by passing in the image tile provider object.
    <script type="text/javascript" src='demo.js'></script>