Custom Map Styles

The HERE SDK for Flutter provides a flexible solution to customize the map by loading custom map schemes.

If you are looking for predefined map styles, see the Quick Start guide for an introduction. The HERE SDK already includes a set of pre-configured map styles such as .normalDay or .satellite.

Create and Load Custom Map Styles

The most flexible solution to customize the map is to create your own map styles using a configuration file generated with the WYSIWYG HERE Style Editor.

Note

The web-based unified HERE Style Editor is available on the HERE platform. It is compatible with the Maps API for JavaScript (JSAPI) and the HERE SDK since version 4.12.1.0. Custom map styles that have been made with the legacy desktop editor need to be migrated to the new HERE Style Editor format. Get in touch with your HERE representative to discuss potential style updates from legacy editions.

Screenshot: The HERE Style Editor showing a custom map configuration.

In order to use the HERE Style Editor, perform the following steps:

  1. Sign-up for an account on the HERE platform.
  2. Confirm and finalize your account generation by providing addition details.
  3. Select HERE Style Editor from the Launcher Menu on your landing page on the HERE platform or use this direct link after signing in.
  4. Start utilizing the HERE Style Editor by selecting one of the existing base styles you want to customize.
  5. Apply your customizations to the map style.
  6. Finalize your work by exporting the customized map style to your local computer via File -> Export Map Style and load it to your application as described below.

Copy the resulting JSON into the "assets" directory of your project. If not already added, you can add that folder via Android Studio (Right-click on the project: New -> Folder -> Assets folder). You can also manually generate the folder: /your_app/assets. This folder also needs to be included into your pubspec.yaml:

# The following section is specific to Flutter.
flutter:

  # Here we store our custom map styles.
  assets:
    - assets/

Load the style into a map scene as follows:

void loadCustomMapStyle() {
  File file = File("assets/custom-dark-style-neon-rds.json");
  String filePath = file.path;
  _hereMapController.mapScene.loadSceneFromConfigurationFile(filePath, (MapError? error) {
    if (error == null) {
      // Scene loaded.
    } else {
      print("Map scene not loaded. MapError: " + error.toString());
    }
  });
}

In the above snippet, we use Flutter's File class to verify that the *.json file exists at the expected location.

Screenshot: Another example for a custom map style configuration.

Using custom map styles can be very effective to differentiate your app from other map applications. In addition, it is possible to change map styles on-the-fly, for example, to shift the user's attention to certain map elements based on the current state of your app.

Note

You can find a CustomMapStyles example app on GitHub.

A collection of screenshots showing a variety of custom map style configurations.

Load Custom Raster Layers

Another alternative to customize the map's look is to add your own raster tile service on top of the HERE map styles. This can be your own server where you host tiles that you want to show as an overlay on top of selected areas of the world - or a public tile server such as OpenStreetMap. Fully opaque and transparent map tile overlays are supported. It is also possible to add more than one raster layer to the map at the same time.

Note

Note that this is a beta release of this feature, so there could be a few bugs and unexpected behaviors. Related APIs may change for new releases without a deprecation process.

To add custom raster layers, you need to create a RasterDataSource. A RasterDataSource represents the source of raster tile data to display. It also allows changing its configuration. With a RasterDataSourceConfiguration you can specify a configuration for the data source, including URL, tiling scheme, storage levels and caching parameters.

Finally, with the MapLayerBuilder you can create a MapLayer to add a renderable map overlay to the map.

  • Use MapLayerVisibilityRange to specify at which zoom levels the map layer should become visible.
  • Use the MapLayerPriority to specify the draw order of the MapLayer.
  • Use the MapContentType to specify the type of data to be shown by the MapLayer.

In case of raster tile images, use MapContentType.rasterImage.

Default map gesture actions such as pinch, rotate and zoom behave in the same way for raster tiles as for HERE vector maps - except for a few differences: For example, raster tiles are loaded as bitmaps and therefore a rotated raster map tile rotates all labels and street names contained together with the tile.

Note

When loading a map scene with a custom map style or the default map style, the map will be rendered using vector tiles where the map information is represented as vector data consisting of vertices and paths for better scalability and performance. By contrast, raster tiles are regularly-spaced and square, and consist of bitmap images that represent only pixel information. Note that the satellite map style is also raster based.

Create a RasterDataSource as follows:

RasterDataSource _createRasterDataSource(String dataSourceName) {
  // The URL template that is used to download tiles from the device or a backend data source.
  String templateUrl = "https://stamen-tiles.a.ssl.fastly.net/toner/{z}/{x}/{y}.png";
  // The storage levels available for this data source. Supported range [0, 31].
  List<int> storageLevels = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
  RasterDataSourceProviderConfiguration rasterProviderConfig =
      RasterDataSourceProviderConfiguration.withDefaults(templateUrl, TilingScheme.quadTreeMercator, storageLevels);

  // Raster tiles are stored in a separate cache on the device.
  String path = "cache/raster/toner";
  int maxDiskSizeInBytes = 1024 * 1024 * 128; // 128 MB
  RasterDataSourceCacheConfiguration cacheConfig = RasterDataSourceCacheConfiguration(path, maxDiskSizeInBytes);

  // Note that this will make the raster source already known to the passed map view.
  return RasterDataSource(_hereMapController.mapContext,
      RasterDataSourceConfiguration.withDefaults(dataSourceName, rasterProviderConfig, cacheConfig));
}

This code uses a tile source from Stamen Design, which can be used under the CC BY 3.0 license. The data itself comes from OpenStreetMap. For more information visit http://maps.stamen.com/#watercolor/12/37.7706/-122.3782.

Note that you can also use other tile sources that follow the OSM standard style format /zoom/x/y.png. The templateURL should look like this:

https://YourRasterTileService.com/{zoom}/{xTile}/{yTile}.png

Here, the zoom value represents the map's current zoom level, and xTile and yTile defines the horizontal and vertical tile numbers. For example, to show the standard OSM map, use the following template URL:

let templateUrl = "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"

More tile servers following the OSM format are listed here. Note that the HERE SDK supports only tile servers. Servers that provide vector data are not supported. Vector based tiles can only be used with the HERE Style Editor and the embedded map styles (see above).

Once a tile source is created, a MapLayer can be built:

MapLayer _createMapLayer(String dataSourceName) {
  // The layer should be rendered on top of other layers.
  MapLayerPriority priority = MapLayerPriorityBuilder().renderedLast().build();
  // And it should be visible for all zoom levels.
  MapLayerVisibilityRange range = MapLayerVisibilityRange(0, 22 + 1);

  try {
    // Build and add the layer to the map.
    MapLayer mapLayer = MapLayerBuilder()
        .forMap(_hereMapController.hereMapControllerCore) // mandatory parameter
        .withName(dataSourceName + "Layer") // mandatory parameter
        .withDataSource(dataSourceName, MapContentType.rasterImage)
        .withPriority(priority)
        .withVisibilityRange(range)
        .build();
    return mapLayer;
  } on MapLayerBuilderInstantiationException {
    throw Exception("MapLayer creation failed.");
  }
}

And finally, the MapTile's visibility can be controlled by enabling or disabling the layer. Note that we also need to provide a unique name. Each RasterDataSource can be created only once:

String dataSourceName = "myRasterDataSourceTonerStyle";
_rasterDataSourceTonerStyle = _createRasterDataSource(dataSourceName);
_rasterMapLayerTonerStyle = _createMapLayer(dataSourceName);

_rasterMapLayerTonerStyle?.setEnabled(true);

The resulting layer looks like this:

Screenshot: A b/w toner style map layer from Stamen Design shown on top of a map view.

The above screenshot shows that you can easily combine custom raster tiles with other HERE SDK features. For example, you can render several MapMarker instances on top of the tile data from a tile server.

Note

One of the main advantages of custom raster layers is that you can easily enhance the HERE map styles with a transparent custom tile source on top, for example, to show weather data or any other data you want to see on top of the map. When using an opaque raster tile source, it is recommended to combine this with an empty base map style.

If you do not use an empty base map style, then the underlying map scheme will "shine" through until the raster layer tiles are loaded. The accompanying example app shows how this looks like.

There are certain other parameters that you can adjust:

  • For example, if your app uses multiple raster layers, you can define a load priority when building a layer with the MapLayerBuilder. This allows to specify an integer value: Higher values will lead to load the layer before layers with lower values. Note that this controls just the time when the layer is loaded, the MapLayerPriority controls how the layer is rendered: For example, renderedLast() means that the layer will be rendered on top of all other layers.
  • For showing transparent map styles, set rasterProviderConfig.hasAlphaChannel to true.
  • For more parameters, please consult the API Reference.

results matching ""

    No results matching ""