Maps API for JavaScript Developer's Guide

Migration to the Maps API for JavaScript 3.1

The article outlines migration path from HERE Maps API for JavaScript 3.0 to the version 3.1 and describes in greater details backwards incompatible changes. For more details about API versioning refer to the API versions chapter of the current guide.

Version 3.1 of Maps API for JavaScript introduces the new default WebGL-based rendering engine that provides efficient vector rendering, increases map performance and gives richer experience for developer and the end user. The new rendering engine brings a number of changes in how API behaves as well as it shifts a set of functionalities related to the 2D HTML5 Canvas engine to the "legacy" modules.

API key instead of app_id and app_code

The new way to authenticate the application was introduces in the HERE Maps API for JavaScript version 3.1. It utilizes the apikey instead of the app_id and app_code pair. The code below shows how to instantiate a H.service.Platform in the new version of the API:

var platform = new H.service.Platform({
  'apikey': '{YOUR_APIKEY}'
});
      

Legacy Modules

Two auxiliary modules were introduced to the Maps API for JavaScript in order to ensure smooth transition from version 3.0 to 3.1. This modules ensure that applications that do not have access to the latest browser technology still can benefit from the HERE services. There are two modules available:
  • mapsjs-core-legacy.js - brings HTML5 canvas rendering engine and it's associated functionality
  • mapsjs-service-legacy.js = provides the access to the legacy platform services (ex. HTML5 meta-info tiles)
In order to use the modules just include them on the page. It's important to include these files after the module they depend on. For example:
<!DOCTYPE html>
  <html>
  <head>
    ...
    <meta name="viewport" content="initial-scale=1.0,
    width=device-width" />
    <script src="https://js.api.here.com/v3/3.1/mapsjs-core.js"
    type="text/javascript" charset="utf-8"></script>
    <script src="https://js.api.here.com/v3/3.1/mapsjs-core-legacy.js"
    type="text/javascript" charset="utf-8"></script>
    <script src="https://js.api.here.com/v3/3.1/mapsjs-service.js"
    type="text/javascript" charset="utf-8"></script>
    <script src="https://js.api.here.com/v3/3.1/mapsjs-service-legacy.js"
    type="text/javascript" charset="utf-8"></script>
    ...
  </head>
Note how *-legacy modules immediately follow core and service modules.

WebGL as a Default Engine

There is a new default rendering engine in the Maps API for JavaScript version 3.1. The engine uses a HTML5 WebGL canvas element and enables rendering of rich and customizable vector maps. The engine is capable of rendering both, vector and raster data, so for the application that utilizes JavaScript API the change will automatically take place. The only thing that might affect the application is if the base layer in use does not send CORS requests. It is still possible to use the HTML5 canvas 2D rendering engine if the application can't be run in the modern browser that supports WebGL rendering. In order to make the most of the WebGL engine, it is advised to use the new vector tiles.

In the Maps API for JavaScript version 3.0 the map with raster tiles was initialized as follows:
// Obtain the default map types from the platform object:
var defaultLayers = platform.createDefaultLayers();

// Instantiate (and display) a map object:
var map = new H.Map(
  document.getElementById('mapContainer'),
  defaultLayers.normal.map,
  {
    zoom: 10,
    center: { lat: 52.5, lng: 13.4 }
  });
The snippet below shows how to switch to the vector tiles:
// Obtain the default map types from the platform object:
var defaultLayers = platform.createDefaultLayers();

// Instantiate (and display) a map object:
var map = new H.Map(
  document.getElementById('mapContainer'),
  defaultLayers.vector.normal.map,
  {
    zoom: 10,
    center: { lat: 52.5, lng: 13.4 }
  });
The snippet below shows how to use canvas 2D rendering engine on legacy supported browsers:
// Obtain the default map types from the platform object:
var defaultLayers = platform.createDefaultLayers();

// Instantiate (and display) a map object:
var map = new H.Map(
  document.getElementById('mapContainer'),
  defaultLayers.raster.normal.map,
  {
    zoom: 10,
    center: { lat: 52.5, lng: 13.4 },
    engineType: H.map.render.RenderEngine.EngineType.P2D
  });

Default layers collection

The changes in rendering were reflected in the structure of the default layers collection created by the method H.service.Platform#createDefaultLayers. This collection holds the set of the base layers and overlays and provides an easy way to change the appearance of the map.

The following pseudocode demonstrates how the collection of the default layers was structured in Maps API for JavaScript version 3.0:

{
incidents: <Layer>,
normal: {
  base: <Layer>,
  basenight: <Layer>,
  labels: <Layer>,
  map: <Layer>,
  mapnight: <Layer>,
  metainfo: <Layer>,
  panorama: <Layer>,
  panoramanight: <Layer>,
  traffic: <Layer>,
  trafficnight: <Layer>,
  transit: <Layer>,
  xbase: <Layer>,
  xbasenight: <Layer>
},
satellite: {
  base: <Layer>,
  labels: <Layer>,
  map: <Layer>,
  metainfo: <Layer>,
  panorama: <Layer>,
  traffic: <Layer>,
  xbase: <Layer>,
},
terrain: {
  base: <Layer>,
  labels: <Layer>,
  map: <Layer>,
  metainfo: <Layer>,
  panorama: <Layer>,
  traffic: <Layer>,
  xbase: <Layer>,
},
venues:  <Layer>
}
        
Version 3.1 of Maps API for JavaScript introduces new vector layers which can be used only with the WebGL rendering engine. That affected how the above mentioned collection is structured. The collection is split into two groups vector and raster. raster group of layers can be used both with the HTML5 Canvas rendering and the WebGL rendering, meanwhile vector holds layers that are used only with the WebGL rendering. The follow pseudocode demonstrates the new structure of the object:

{
raster: {
  normal: {
    base: <Layer>,
    basenight: <Layer>,
    labels: <Layer>,
    map: <Layer>,
    mapnight: <Layer>,
    trafficincidents: <Layer>,
    transit: <Layer>,
    xbase: <Layer>,
    xbasenight: <Layer>
  },
  satellite: {
    base: <Layer>,
    labels: <Layer>,
    map: <Layer>,
    xbase: <Layer>
  },
  terrain: {
    base: <Layer>,
    labels: <Layer>,
    map: <Layer>,
    xbase: <Layer>
  }
},
vector: {
  normal: {
    map: <Layer>,
    traffic: <Layer>,
    trafficincidents: <Layer>
  }
}
}
        
The changes in the structure of the default layers collection affect the way H.ui.MapSettingsControl is created. In the previous version of the API the code below was used to create a custom map settings control:

// 'maptypes' variable holds the result of the H.service.Platform#createDefaultLayers call
var mapSettings = new H.ui.MapSettingsControl({
  alignment: 'top-right',
  entries: [{
    name: 'Normal map',
    mapType: maptypes.normal
  }]
});
ui.addControl('mapsettings', mapSettings);
        
In the new version of the API the options parameter was changed to accept an array of baseLayers with the associated labels defined as a H.ui.MapSettingsControl.Entry typedef:

// 'maptypes' variable holds the result of the H.service.Platform#createDefaultLayers call
var mapSettings = new H.ui.MapSettingsControl({
  alignment: 'top-right',
  baseLayers: [{
  label: 'Normal map',
  layer: maptypes.raster.normal.map
  }]
});
ui.addControl('mapsettings', mapSettings);
        

Asynchronous "getObjectAt" interface

The signature and behavior of the method H.Map#getObjectAt responsible for fetching map objects at the given XY screen coordinate was changed. In the version 3.1 of the API it became asynchronous and accepts a callback as third parameter. For example, in the old version it was possible to get the map object synchronously:
// Provided that map is instantiated and there are some markers
// on the map that must be inspected.
var obj = map.getObjectAt(0, 0);
if (obj && obj instanceof H.map.Marker) {
  console.log(obj.getPosition());
}
With the new version the same code should be executed in the callback:
// Provided that map is instantiated and there are some markers
// on the map that must be inspected.
map.getObjectAt(0, 0, (obj) => {
  if (obj && obj instanceof H.map.Marker) {
    console.log(obj.getGeometry());
  }
});

LookAt interface

The functionality related to the H.map.ViewModel.CameraData interface was deprecated and similar functionality is provided by methods related to the H.map.ViewModel.ILookAtData. Methods that were removed are:
  • H.map.ViewModel#getCameraData
  • H.map.ViewModel#setCameraData
  • H.Map#screenToCameraData
These above mentioned methods were replaced by the following methods accordingly:
  • H.map.ViewModel#getLookAtData
  • H.map.ViewModel#setLookAtData
  • H.Map#screenToLookAtData
The method H.Map#getCameraDataForBound was deprecated and removed. The corresponding functionality can be achieved by using the H.map.ViewModel.ILookAtData#bounds property, that contains the geometry that represents the visible bounds including the tilt and rotation of the map. The same is applicable to the methods H.map.ViewModel#setZoom and H.map.ViewModel#getZoom, those methods were removed and instead of them H.map.ViewModel.ILookAtData#zoom property must be used.

The changes in the LookAt interface also affected the H.Map class. The methods H.Map#setViewBounds, H.Map#getViewBounds and H.Map#getCameraDataForBounds were removed and direct calls to the H.map.ViewModel must be utilized.

Fractional zoom levels

The new rendering engine of HERE Maps API for JavaScript supports fractional zoom levels. That gives the end user better control over the map. This behavior is turned on by default. If that's not the desired map behavior, for example in case of a raster-based overlay or legacy application, it is possible to switch it off. The following code snippet demonstrates how to disable fractional zoom levels on a H.mapevents.Behavior instance and UI ZoomControl
// Provided that the map, UI and mapevents behavior are instantiated

// disable fractional zooming for Behavior
behavior.disable(H.mapevents.Behavior.Feature.FRACTIONAL_ZOOM);

// instantiate H.ui.ZoomControl with the disabled fractional zooming
// and add it to the UI
var zoomControl = new H.ui.ZoomControl({fractionalZoom: false});
ui.addControl('zoom', zoomControl);

StreetLevel and Places modules

In the version 3.1 of HERE Maps API for JavaScript the module responsible for the StreetLevel Imagery (mapsjs-pano.js) and the dedicated Places (mapsjs-places.js) module are deprecated. While Places REST API functionality is available through the corresponding classes in mapsjs-service.js module, StreetLevel Imagery was deprecated and removed from the JavaScript API. The associated functionality to switch the render engine, such as H.Map#event:enginechange and H.Map#setEngineType were removed. Besides, StreetLevel UI element (mapsjs.ui.Pano) was removed.

Traffic incidents and traffic flow service

H.service.TrafficIncidentsProvider and H.service.TrafficIncidentsService were renamed and moved into the new namespace: H.service.traffic.incidents.Provider and H.service.traffic.Service correspondingly, functionality of these classes remained unchanged.

Besides there is a new recommended way to display traffic flow information, provided by the Traffic REST API, on the map compatible with the new WebGL rendering engine. While in the old approach the data was pre-rendered as an image on the server side, the new way utilizes vector rendering which enables interactions with the rendered data. In the following code sample new instance of the Traffic service is created and then it is used to create a Traffic Flow Provider that is used to display data on the map.
// Provided that map and platform objects are instantiated.
// Create a traffic service and a corresponding provider.
var service = platform.getTrafficService()
var provider = new H.service.traffic.flow.Provider(service)

// Create a tile layer that can be added to the map
var layer = new H.map.layer.TileLayer(provider);
map.addLayer(layer);

Geo shapes and map objects

The following methods related to the calculation of the geometries' bounding box were renamed, the signature of the methods remained intact:
  • H.geo.AbstractGeometry#getBounds renamed to H.geo.AbstractGeometry#getBoundingBox
  • H.geo.Point#getBounds renamed to H.geo.Point#getBoundingBox
  • H.geo.Rect#getBounds renamed to H.geo.Rect#getBoundingBox
  • H.geo.LineString#getBounds renamed to H.geo.LineString#getBoundingBox
  • H.geo.MultiGeometry#getBounds renamed to H.geo.MultiGeometry#getBoundingBox
  • H.geo.MultiLineString#getBounds renamed to H.geo.MultiLineString#getBoundingBox
  • H.geo.Polygon#getBounds renamed to H.geo.Polygon#getBoundingBox
  • H.geo.MultiPolygon#getBounds renamed to H.geo.MultiPolygon#getBoundingBox
  • H.geo.MultiPoint#getBounds renamed to H.geo.MultiPoint#getBoundingBox
The class H.geo.Strip was deprecated in HERE Maps API for JavaScript 3.0 and removed in the new version – the H.geo.LineString must be used instead. Respectively the methods responsible for the calculation of the bounding box for the map objects were adjusted:
  • H.map.Circle#getBounds renamed to H.map.Circle#getBoundingBox
  • H.map.GeoShape#getBounds renamed to H.map.GeoShape#getBoundingBox
  • H.map.Group#getBounds renamed to H.map.Group#getBoundingBox
  • H.map.Overlay#getBounds renamed to H.map.Overlay#getBoundingBox
  • H.map.Polygon#getBounds renamed to H.map.Polygon#getBoundingBox
  • H.map.Polyline#getBounds renamed to H.map.Polyline#getBoundingBox
  • H.map.Rect#getBounds renamed to H.map.Rect#getBoundingBox
  • H.clustering.ICluster#getBounds renamed to H.clustering.ICluster#getBoundingBox
The map objects' methods to set and get underlying geometries were changed to reflect the fact that objects could be created with different geometries. To get the geometry, changes are as follows:
  • mapsjs.map.AbstractMarker#getPosition renamed to mapsjs.map.AbstractMarker#getGeometry
  • mapsjs.map.Circle#getStrip renamed to mapsjs.map.Circle#getGeometry
  • mapsjs.map.DomMarker#getPosition renamed to mapsjs.map.DomMarker#getGeometry
  • mapsjs.map.GeoShape#getStrip renamed to mapsjs.map.GeoShape#getGeometry
  • mapsjs.map.Marker#getPosition renamed to mapsjs.map.Marker#getGeometry
  • mapsjs.map.Polygon#getStrip renamed to mapsjs.map.Polygon#getGeometry
  • mapsjs.map.Polyline#getStrip renamed to mapsjs.map.Polyline#getGeometry
  • mapsjs.map.Rect#getStrip renamed to mapsjs.map.Rect#getGeometry
And to set the geometry, changes are as follows:
  • mapsjs.map.AbstractMarker#setPosition renamed to mapsjs.map.AbstractMarker#setGeometry
  • mapsjs.map.Circle#setStrip renamed to mapsjs.map.Circle#setGeometry
  • mapsjs.map.DomMarker#setPosition renamed to mapsjs.map.DomMarker#setGeometry
  • mapsjs.map.GeoShape#setStrip renamed to mapsjs.map.GeoShape#setGeometry
  • mapsjs.map.Marker#setPosition renamed to mapsjs.map.Marker#setGeometry
  • mapsjs.map.Polygon#setStrip renamed to mapsjs.map.Polygon#setGeometry
  • mapsjs.map.Polyline#setStrip renamed to mapsjs.map.Polyline#setGeometry
  • mapsjs.map.Rect#setStrip renamed to mapsjs.map.Rect#setGeometry
Besides the above mentioned changes in the map objects' method names, all events related to them were deprecated and removed, namely:
  • visibilitychange
  • zindexchange
  • stylechange
  • stripchange