All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vaadin.flow.component.map.Map Maven / Gradle / Ivy

There is a newer version: 24.5.5
Show newest version
/**
 * Copyright 2000-2023 Vaadin Ltd.
 *
 * This program is available under Vaadin Commercial License and Service Terms.
 *
 * See  for the full
 * license.
 */
package com.vaadin.flow.component.map;

import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.component.map.configuration.Configuration;
import com.vaadin.flow.component.map.configuration.Coordinate;
import com.vaadin.flow.component.map.configuration.View;
import com.vaadin.flow.component.map.configuration.feature.MarkerFeature;
import com.vaadin.flow.component.map.configuration.layer.FeatureLayer;
import com.vaadin.flow.component.map.configuration.layer.ImageLayer;
import com.vaadin.flow.component.map.configuration.layer.Layer;
import com.vaadin.flow.component.map.configuration.layer.TileLayer;
import com.vaadin.flow.component.map.configuration.layer.VectorLayer;
import com.vaadin.flow.component.map.configuration.source.OSMSource;
import com.vaadin.flow.component.map.configuration.source.Source;
import com.vaadin.flow.component.map.configuration.source.VectorSource;
import com.vaadin.flow.component.map.configuration.source.XYZSource;

import java.util.Objects;

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

* Each map consists of one or more {@link Layer}s that display geographical * data. Each layer has a {@link Source} that provides that data. The Map * component provides several types of layers (for example {@link TileLayer}, * {@link VectorLayer}, {@link ImageLayer}), as well as several types of sources * that can be used with each type of layer (for example {@link OSMSource}, * {@link XYZSource}, {@link VectorSource}). *

* The map component comes pre-configured with a background layer, which by * default is a {@link TileLayer} using an {@link OSMSource}, which means that * it displays tiled image data from the OpenStreeMap service. The background * layer of the map can be replaced using {@link #setBackgroundLayer(Layer)}. * The component is also pre-configured with a {@link FeatureLayer}, accessible * with {@link #getFeatureLayer()}, that allows to quickly display geographical * features, such as markers (see {@link MarkerFeature}), on top of a map. * Custom layers can be added or removed using {@link #addLayer(Layer)} and * {@link #removeLayer(Layer)}. *

* The viewport of the map is controlled through a {@link View}, which allows * setting the center, zoom level and rotation. The map's view can be accessed * through {@link Map#getView()}. *

* The default projection, or coordinate system, for all coordinates passed to, * or returned from the public API is {@code EPSG:4326}, also referred to as GPS * coordinates. This is called the user projection. Internally the component * converts all coordinates into the projection that is used by the map's * {@link View}, which is referred to as the view projection. The user * projection can be changed using {@link #setUserProjection(String)}. Out of * the box, the map component has support for the {@code EPSG:4326} and * {@code EPSG:3857} projections. Custom coordinate projections can be defined * using {@link #defineProjection(String, String)}. */ @Tag("vaadin-map") @NpmPackage(value = "@vaadin/map", version = "24.3.12") @NpmPackage(value = "proj4", version = "2.9.2") @JsModule("@vaadin/map/src/vaadin-map.js") @JsModule("./vaadin-map/mapConnector.js") public class Map extends MapBase { private Layer backgroundLayer; private final FeatureLayer featureLayer; /** * Sets the projection (or coordinate system) to use for all coordinates. * That means that all coordinates passed to, or returned from the public * API, must be in this projection. Internally the coordinates will be * converted into the projection that is used by the map's {@link View}. *

* By default, the user projection is set to {@code EPSG:4326}, also known * as latitude / longitude, or GPS coordinates. *

* This setting affects all maps in the current {@link UI}, currently it is * not possible to configure this per map instance. This method may only be * invoked inside of UI threads, and will throw otherwise. This setting * being scoped to the current UI means that it will stay active when * navigating between pages using the Vaadin router, but not when doing a * "hard" location change, or when reloading the page. As such it is * recommended to apply this setting on every page that displays maps. Note * that when using the preserve on refresh feature, a view's constructor is * not called. In that case this setting can be applied in an attach * listener. *

* This method should be called before creating any maps. Changing this * setting does not affect existing maps, specifically the component does * not convert coordinates configured in an existing map into the new * projection. Instead, existing maps should be recreated after changing * this setting. * * @param projection * the user projection to use for all public facing API */ public static void setUserProjection(String projection) { UI ui = UI.getCurrent(); if (ui == null || ui.getPage() == null) { throw new IllegalStateException("UI instance is not available. " + "It means that you are calling this method " + "out of a normal workflow where it's always implicitly set. " + "That may happen if you call the method from the custom thread without " + "'UI::access' or from tests without proper initialization."); } UI.getCurrent().getPage().executeJs( "window.Vaadin.Flow.mapConnector.setUserProjection($0)", projection); } /** * Defines a custom coordinate projection that can then be used as user * projection or view projection. Defining a projection requires a name, * which is then used to reference it when setting a user or view * projection, as well as a projection definition in the Well Known Text * (WKS) format. A handy resource for looking up WKS definitions is * epsg.io, which allows to search for * projections, get coordinates from a map, as well as transform coordinates * between projections. *

* This definition is valid for the lifetime of the current {@link UI}. This * method may only be invoked inside of UI threads, and will throw * otherwise. This definition being scoped to the current UI means that it * will stay active when navigating between pages using the Vaadin router, * but not when doing a "hard" location change, or when reloading the page. * As such it is recommended to apply this definition on every page that * displays maps. Note that when using the preserve on refresh feature, a * view's constructor is not called. In that case this definition can be * applied in an attach listener. *

* This method should be called before creating any maps that want to make * use of this projection, and before setting it as a custom user * projection. * * @see #setUserProjection(String) * @see View * @param projectionName * the name of the projection that can be referenced when setting * a user or view projection * @param wksDefinition * the Well Known Text (WKS) definition of the projection */ public static void defineProjection(String projectionName, String wksDefinition) { UI ui = UI.getCurrent(); if (ui == null || ui.getPage() == null) { throw new IllegalStateException("UI instance is not available. " + "It means that you are calling this method " + "out of a normal workflow where it's always implicitly set. " + "That may happen if you call the method from the custom thread without " + "'UI::access' or from tests without proper initialization."); } UI.getCurrent().getPage().executeJs( "window.Vaadin.Flow.mapConnector.defineProjection($0, $1)", projectionName, wksDefinition); } public Map() { super(); // Setup default background layer OSMSource source = new OSMSource(); TileLayer backgroundLayer = new TileLayer(); backgroundLayer.setSource(source); setBackgroundLayer(backgroundLayer); // Setup default feature layer featureLayer = new FeatureLayer(); addLayer(featureLayer); // Simple solution for rendering the feature layer on top of custom // layers by default. Developers can customize the z-index if they want // a different rendering order. featureLayer.setzIndex(100); } public Configuration getRawConfiguration() { return getConfiguration(); } /** * Background layer of the map. Every new instance of a {@link Map} is * initialized with a background layer. By default, the background layer * will be a {@link TileLayer} using an {@link OSMSource}, which means it * will display tiled map data from the official OpenStreetMap server. * * @return the background layer of the map */ public Layer getBackgroundLayer() { return backgroundLayer; } /** * Sets the background layer of the map. The layer will be prepended before * all other layers, which means it will be rendered in the background by * default. The background layer is not intended to be removed, and thus can * not be set to null. For use-cases where you want to use a dynamic set of * layers, consider setting the first layer as background layer, and then * adding the remaining layers using {@link #addLayer(Layer)}. * * @param backgroundLayer * the new background layer, not null */ public void setBackgroundLayer(Layer backgroundLayer) { Objects.requireNonNull(backgroundLayer); if (this.backgroundLayer != null) { getConfiguration().removeLayer(this.backgroundLayer); } this.backgroundLayer = backgroundLayer; getConfiguration().prependLayer(backgroundLayer); } /** * The feature layer of the map. Every new instance of a {@link Map} has a * pre-configured {@link FeatureLayer} for convenience, to allow quickly * adding geographical features without requiring to set up a layer. Note * that it is possible to add additional feature layers with * {@link #addLayer(Layer)} if splitting up features into different layers * is beneficial for a use-case. * * @return the feature layer of the map */ public FeatureLayer getFeatureLayer() { return featureLayer; } /** * Adds a layer to the map. The layer will be appended to the list of * layers, meaning that it will be rendered last / on top of previously * added layers by default. For more fine-grained control of the layer * rendering order, use {@link Layer#setzIndex(Integer)}. * * @param layer * the layer to be added */ public void addLayer(Layer layer) { getConfiguration().addLayer(layer); } /** * Remove a layer from the map * * @param layer * the layer to be removed */ public void removeLayer(Layer layer) { getConfiguration().removeLayer(layer); } /** * Gets center coordinates of the map's viewport *

* This is a convenience method that delegates to the map's internal * {@link View}. See {@link #getView()} for accessing other properties of * the view. * * @return current center of the viewport */ public Coordinate getCenter() { return getView().getCenter(); } /** * Sets the center of the map's viewport. Coordinates must be specified in * the map's user projection, which by default is {@code EPSG:4326}, also * referred to as GPS coordinates. If the user projection has been changed * using {@link Map#setUserProjection(String)}, then coordinates must be * specified in that projection instead. *

* This is a convenience method that delegates to the map's internal * {@link View}. See {@link #getView()} for accessing other properties of * the view. *

* Note that the user projection is a different concept than the view * projection set in the map's {@link View}. The view projection affects how * map data is interpreted and rendered, while the user projection defines * the coordinate system that all coordinates passed to, or returned from * the public API must be in. * * @param center * new center of the viewport */ public void setCenter(Coordinate center) { getView().setCenter(center); } /** * Gets zoom level of the map's viewport, defaults to {@code 0} *

* This is a convenience method that delegates to the map's internal * {@link View}. See {@link #getView()} for accessing other properties of * the view. * * @return current zoom level */ public double getZoom() { return getView().getZoom(); } /** * Sets the zoom level of the map's viewport. The zoom level is a decimal * value that starts at {@code 0} as the most zoomed-out level, and then * continually increases to zoom further in. By default, the maximum zoom * level is currently restricted to {@code 28}. In practical terms, the * level of detail of the map data that a map service provides determines * how useful higher zoom levels are. *

* This is a convenience method that delegates to the map's internal * {@link View}. See {@link #getView()} for accessing other properties of * the view. * * @param zoom * new zoom level */ public void setZoom(double zoom) { getView().setZoom(zoom); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy