Documentation

Documentation versions (currently viewingVaadin 23)

Map

Note
Commercial feature

A commercial Vaadin subscription is required to use Map in your project.

Important
Experimental Feature

Map is currently considered an experimental feature, which means that its behavior, API, and look and feel might still change. In order to use Map, it must be explicitly enabled with a feature flag. See the Feature Flag section for how to do this.

Map is a component for displaying geographical maps from various sources. It supports multiple layers, tiled and full-image sources, adding markers, and interaction through events.

Important
Map Data Subscription Not Included

The Map component uses OpenStreetMap as its default map data provider for testing and development purposes. The tile usage policy for OpenStreetMap only allows for light usage, which means that it should not be used for production. A commercial map data service, or a self-hosted solution, should be arranged for production use. See the Map Sources section for a list of supported map data formats.

Open in a
new tab
// Create a new map, this will use the OpenStreetMap service by default
Map map = new Map();
add(map);

Viewport

Map provides interactions, controls, and APIs to control the viewport. This includes setting the center, the zoom level, and the rotation.

By default, map coordinates, such as the view’s center, are specified in EPSG:3857 / Web Mercator Projection, unless the map service uses a custom projection. As coordinates are often provided as latitude and longitude, Map provides utilities for converting these into Web Mercator projection.

The zoom level is a decimal number that starts at zero as the most zoomed-out level, and then progressively increases to zoom further in. By default, the maximum zoom level is currently restricted to 28. In practical terms, the level of detail of the map data that a map service provides determines the usefulness of higher zoom levels.

Open in a
new tab
MenuBar menuBar = new MenuBar();
SubMenu moveToSubMenu = menuBar.addItem("Move To...").getSubMenu();

// Add menu items for moving the viewport to different cities
moveToSubMenu.addItem("Berlin", e -> {
    Coordinate coordinate = Coordinate.fromLonLat(13.404954, 52.520008);
    map.getView().setCenter(coordinate);
    map.getView().setZoom(10);
});

...

// Add menu items for zooming
menuBar.addItem(zoomInIcon, e -> {
    float zoom = map.getView().getZoom();
    map.getView().setZoom(zoom + 1);
});
menuBar.addItem(zoomOutIcon, e -> {
    float zoom = map.getView().getZoom();
    map.getView().setZoom(zoom - 1);
});

Map Sources

Web maps can be roughly categorized as being based on tiled images, full images or vector data. Each category comes with its own set of standards and formats that define how the map data is structured and how it should be used. Map services are applications (typically servers or cloud services) that provide map data in one or more of these formats.

The Map component provides various sources for loading map data in a specific format from a map service. Note that each source requires the use of a specific type of layer that can render data from that source.

The following table lists the sources that can be used with Map. An example usage of each source can be found in the demo that follows:

SourceRequiresDescription

OSM

Tile layer

Loads image tiles from the OpenStreetMap service. This source is configured as the default. It does not require further configuration, as it contains presets for URL and attributions. This source should be used only for development purposes. For applications in production, we encourage you to use a commercial map service or a self-hosted solution. Please read and respect the OpenStreetMap tile usage policy.

XYZ

Tile layer

Loads image tiles from a map service that supports the Slippy Map tile numbering scheme, also known as XYZ format. This source requires you to configure a URL pattern that contains placeholders for the x and y tile coordinates, as well as the z placeholder for the zoom level; for example, https://my-map-service.com/my-tileset/{z}/{x}/{y}.png. For the specific URL, consult the documentation of the map service that you intend to use.

Tile WMS

Tile layer

Loads image tiles from a Web Map Service (WMS). This source requires you to configure the URL to the WMS, as well as the request parameters. As a minimum, the LAYERS request parameter must be configured. For other required parameters and available values, consult the documentation of the service itself.

Open in a
new tab
private void setupOsmSource() {
    // OSM does not require any further configuration,
    // it contains presets for URL and attributions
    OSMSource source = new OSMSource();
    TileLayer tileLayer = new TileLayer();
    tileLayer.setSource(source);
    map.setBackgroundLayer(tileLayer);
}

private void setupXyzSource() {
    XYZSource.Options sourceOptions = new XYZSource.Options();
    // set the URL pattern for the map service containing x, y, and z parameters
    // mapbox requires an access token, register on
    // mapbox.com to get one, and place it in the line below
    sourceOptions.setUrl("https://api.mapbox.com/v4/mapbox.satellite/{z}/{x}/{y}.jpg90?access_token=<your-access-token>");
    // using a map service usually requires setting
    // attributions with copyright notices
    sourceOptions.setAttributions(List.of(
        "<a href=\"https://www.mapbox.com/about/maps/\">© Mapbox</a>",
        "<a href=\"https://www.openstreetmap.org/about/\">© OpenStreetMap</a>"
    ));
    sourceOptions.setAttributionsCollapsible(false);
    XYZSource source = new XYZSource(sourceOptions);
    TileLayer tileLayer = new TileLayer();
    tileLayer.setSource(source);
    map.setBackgroundLayer(tileLayer);
}

private void setupWmsSource() {
    TileWMSSource.Options sourceOptions = new TileWMSSource.Options();
    // set the URL for the WMS
    sourceOptions.setUrl("https://ows.mundialis.de/services/service");
    // WMS require configuration of request parameters,
    // at least the LAYERS parameter must be specified.
    // Required parameters and possible values can be
    // found in the respective documentation of the service
    HashMap<String, Object> params = new HashMap<>();
    params.put("LAYERS", "TOPO-WMS");
    sourceOptions.setParams(params);
    // using a map service usually requires setting
    // attributions with copyright notices
    sourceOptions.setAttributions(List.of("Contains modified SRTM data (2014)/NASA, processed by <a href=\"https://www.mundialis.de\">mundialis<a/>"));
    sourceOptions.setAttributionsCollapsible(false);
    TileWMSSource source = new TileWMSSource(sourceOptions);
    TileLayer layer = new TileLayer();
    layer.setSource(source);
    map.setBackgroundLayer(layer);
}

Layers

The map component is preconfigured with a background layer showing a map from the OpenStreetMap service by default, as well as a feature layer for quickly adding geographical features, such as markers. The default background layer can be replaced, and additional layers added on top of it, for example to display overlays.

By default, layers are rendered in the order that they were added to the map, with the first-added layer rendered first, and the last-added layer rendered last. For finer-grained control of the layer rendering order, a z-index can be defined for each layer. Layers with a higher z-index are rendered on top of layers with a lower z-index. The exceptions are the background layer, which is always rendered first, and the feature layer, which is rendered with a z-index of 100 by default.

The visibility of layers can be toggled, which can be an alternative to dynamically adding and removing them. For map overlays, a layer can be configured with a lowered opacity, so that the background layer is still semi-visible below the overlay layer. Note that some map services may provide map data with a lowered opacity by default.

The following example demonstrates how to replace the background layer, how to add several overlay layers to the map, and how to control their visibility:

Open in a
new tab
// Replace background layer when option changes
backgroundLayerGroup.addValueChangeListener(e -> {
    LayerOption selectedOption = e.getValue();
    XYZSource.Options sourceOptions = new XYZSource.Options();
    sourceOptions.setUrl(selectedOption.getUrl());
    sourceOptions.setAttributions(List.of(selectedOption.getAttributions()));
    sourceOptions.setAttributionsCollapsible(false);
    XYZSource source = new XYZSource(sourceOptions);
    TileLayer layer = new TileLayer();
    layer.setSource(source);
    map.setBackgroundLayer(layer);
});

...

// Add all overlay layers at once, make them invisible initially
List.of(PRECIPITATION_LAYER, AIR_TEMPERATURE_LAYER, WIND_SPEED_LAYER).forEach(option -> {
    XYZSource.Options sourceOptions = new XYZSource.Options();
    sourceOptions.setUrl(option.getUrl());
    sourceOptions.setAttributions(List.of(option.getAttributions()));
    sourceOptions.setAttributionsCollapsible(false);
    XYZSource source = new XYZSource(sourceOptions);
    TileLayer layer = new TileLayer();
    layer.setSource(source);
    layer.setVisible(false);

    map.addLayer(layer);
    overlayLayerMap.put(option, layer);
});

...

// Toggle visibility of overlay layer when option changes
overlayLayerGroup.addValueChangeListener(e -> {
    LayerOption selectedOption = e.getValue();
    // Make previously selected layer invisible
    if (selectedOverlayLayer != null) {
        selectedOverlayLayer.setVisible(false);
    }
    // Get next selected layer
    selectedOverlayLayer = overlayLayerMap.get(selectedOption);
    // Make selected layer visible, unless it's the none option
    if (selectedOverlayLayer != null) {
        selectedOverlayLayer.setVisible(true);
    }
});

Markers

Markers can be displayed on top of a map to indicate points of interest, such as addresses, buildings, vehicles, or any other entity. A marker is defined by a coordinate and an icon. Icons can be configured as either a URL or a StreamResource. If no custom icon is provided, the marker will use a default icon.

By default, map coordinates, such as a marker’s location, are specified in EPSG:3857 / Web Mercator Projection, unless the map service uses a custom projection. As coordinates are often provided as latitude and longitude, Map provides utilities for converting these into Web Mercator projection.

Open in a
new tab
// Add marker for Vaadin HQ, using default marker image
Coordinate vaadinHqCoordinates = Coordinate.fromLonLat(22.29985, 60.45234);
MarkerFeature vaadinHq = new MarkerFeature(vaadinHqCoordinates);
map.getFeatureLayer().addFeature(vaadinHq);

// Add marker for Vaadin office in Germany, using image from URL
Coordinate germanOfficeCoordinates = Coordinate.fromLonLat(13.45489, 52.51390);
Icon.Options germanFlagIconOptions = new Icon.Options();
germanFlagIconOptions.setSrc("images/german_flag.png");
Icon germanFlagIcon = new Icon(germanFlagIconOptions);
MarkerFeature germanOffice = new MarkerFeature(germanOfficeCoordinates, germanFlagIcon);
map.getFeatureLayer().addFeature(germanOffice);

// Add marker for Vaadin office in the US, using image from a StreamResource
Coordinate usOfficeCoordinates = Coordinate.fromLonLat(-121.92163, 37.36821);
StreamResource streamResource = new StreamResource("us-flag.png",
        () -> getClass().getResourceAsStream("/META-INF/resources/images/us-flag.png"));
Icon.Options usFlagIconOptions = new Icon.Options();
usFlagIconOptions.setImg(streamResource);
Icon usFlagIcon = new Icon(usFlagIconOptions);
MarkerFeature usOffice = new MarkerFeature(usOfficeCoordinates, usFlagIcon);
map.getFeatureLayer().addFeature(usOffice);
Note
Performance considerations

When using custom icons, ensure that you create only one icon instance per custom image that you want to use. For example, when adding multiple markers that use the same image, it is sufficient to create one icon instance and use that for all markers. Creating a separate icon instance for each marker can degrade performance in the browser in terms of memory usage.

Events

The Map component provides several events that can be used to make a map interactive. Currently, the following events are supported:

EventDescription

View Move End

Triggered after the user has changed the viewport, regardless of the input method. The event will be triggered only after the user has finished manipulating the viewport, for example after letting go of the mouse button after a mouse drag interaction.

The event contains details about the current viewport, such as the center, the zoom level, and the current bounding box (extent) of the viewport.

Map Click

Triggered when the user clicks on the map. The event contains information about the clicked coordinates and other details of the mouse event. It also contains a list of all markers at that location in order to distinguish whether the click occurred on the map itself, or on a marker.

Feature Click

Triggered when the user clicks on a marker. The event contains information about the clicked marker and other details of the mouse event. If there are overlapping markers, the event will be fired only for the top-level marker at that location.

The term feature refers to geographical features in a general sense. For now, Map only supports markers as geographical features, so these are equivalent.

The following example demonstrates how to make use of the events:

Open in a
new tab
map.addViewMoveEndEventListener(e -> {
    Coordinate center = e.getCenter();
    Extent extent = e.getExtent();
    String info = "";
    info += String.format("Center = { x: %s, y: %s }%n", center.getX(), center.getY());
    info += String.format("Zoom   = %s%n", e.getZoom());
    info += String.format("Extent = { left: %s, top: %s,%n", extent.getMinX(), extent.getMinY());
    info += String.format("           right: %s, bottom: %s }", extent.getMaxX(), extent.getMaxY());
    viewEventInfo.setValue(info);
});

map.addClickEventListener(e -> {
    Coordinate coordinates = e.getCoordinate();
    String info = String.format("Coordinates = { x: %s, y: %s }", coordinates.getX(), coordinates.getY());
    mapClickInfo.setValue(info);
});

map.addFeatureClickListener(e -> {
    MarkerFeature feature = (MarkerFeature) e.getFeature();
    Coordinate coordinates = feature.getCoordinates();
    // Get city entity for event marker,
    // see remaining example on how the markers are set up
    City city = cityLookup.get(feature);
    String info = "";
    info += String.format("City        = %s%n", city.getName());
    info += String.format("Coordinates = { x: %s, y: %s }", coordinates.getX(), coordinates.getY());
    featureClickInfo.setValue(info);
});

Theme Variants

Borderless

By default, Map has a visible, rounded border. The border can be removed by using the borderless theme variant.

Open in a
new tab
map.addThemeVariants(MapVariant.BORDERLESS);

Feature Flag

In order to use Map, it must be explicitly enabled with a feature flag. There are two methods of doing this:

Using Vaadin Developer Tools

  1. Click on the Vaadin Developer Tools icon button in your running application

  2. Open the Experimental Features tab

  3. Enable the Map component (Pro) feature

  4. Restart the application.

Adding a Feature Flags Properties File

  1. Create a src/main/resources/vaadin-featureflags.properties file in your application folder

  2. Add the following content: com.vaadin.experimental.mapComponent=true

  3. Restart the application.