UNPKG

@here/harp-examples

Version:
193 lines (171 loc) 9.57 kB
/* * Copyright (C) 2020-2021 HERE Europe B.V. * Licensed under Apache 2.0, see full license in LICENSE * SPDX-License-Identifier: Apache-2.0 */ import { FeaturesDataSource, MapViewPointFeature } from "@here/harp-features-datasource"; import { GeoCoordinates } from "@here/harp-geoutils"; import { MapControls, MapControlsUI } from "@here/harp-map-controls"; import { CopyrightElementHandler, MapView } from "@here/harp-mapview"; import { APIFormat, AuthenticationMethod, GeoJsonDataProvider, VectorTileDataSource } from "@here/harp-vectortile-datasource"; import { apikey, copyrightInfo } from "../config"; /** * This examples shows how to render dynamically generated GeoJSON points as markers with picking * support. */ export namespace DynamicMarkersExample { const icons = [ { name: "redIcon", url: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzOCIgaGVpZ2h0PSI0NyIgdmlld0JveD0iMCAwIDM4IDQ3Ij48ZyBmaWxsPSJub25lIj48cGF0aCBmaWxsPSIjMEYxNjIxIiBmaWxsLW9wYWNpdHk9Ii40IiBkPSJNMTUgNDZjMCAuMzE3IDEuNzkuNTc0IDQgLjU3NHM0LS4yNTcgNC0uNTc0YzAtLjMxNy0xLjc5LS41NzQtNC0uNTc0cy00IC4yNTctNCAuNTc0eiI+PC9wYXRoPjxwYXRoIGZpbGw9IiNiNjAxMDEiIGQ9Ik0zMy4yNSAzMS42NTJBMTkuMDE1IDE5LjAxNSAwIDAgMCAzOCAxOS4wNkMzOCA4LjU0OSAyOS40NzggMCAxOSAwUzAgOC41NSAwIDE5LjA1OWMwIDQuODIzIDEuNzk1IDkuMjMzIDQuNzUgMTIuNTkzTDE4Ljk3NSA0NiAzMy4yNSAzMS42NTJ6Ij48L3BhdGg+PHBhdGggZmlsbD0iIzZBNkQ3NCIgZmlsbC1vcGFjaXR5PSIuNSIgZD0iTTI2Ljg2MiAzNy41bDQuNzE0LTQuNzdjMy44MjItMy41NzYgNS45MjQtOC40MTEgNS45MjQtMTMuNjJDMzcuNSA4Ljg0NyAyOS4yLjUgMTkgLjVTLjUgOC44NDguNSAxOS4xMWMwIDUuMjA5IDIuMTAyIDEwLjA0NCA1LjkxOSAxMy42MTRsNC43MTkgNC43NzZoMTUuNzI0ek0xOSAwYzEwLjQ5MyAwIDE5IDguNTI1IDE5IDE5LjA0MSAwIDUuNTA3LTIuMzQ4IDEwLjQ1NC02LjA3OSAxMy45MzJMMTkgNDYgNi4wNzkgMzIuOTczQzIuMzQ4IDI5LjQ5NSAwIDI0LjU0OCAwIDE5LjA0IDAgOC41MjUgOC41MDcgMCAxOSAweiI+PC9wYXRoPjwvZz48L3N2Zz4K" }, { name: "greenIcon", url: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzOCIgaGVpZ2h0PSI0NyIgdmlld0JveD0iMCAwIDM4IDQ3Ij48ZyBmaWxsPSJub25lIj48cGF0aCBmaWxsPSIjMEYxNjIxIiBmaWxsLW9wYWNpdHk9Ii40IiBkPSJNMTUgNDZjMCAuMzE3IDEuNzkuNTc0IDQgLjU3NHM0LS4yNTcgNC0uNTc0YzAtLjMxNy0xLjc5LS41NzQtNC0uNTc0cy00IC4yNTctNCAuNTc0eiI+PC9wYXRoPjxwYXRoIGZpbGw9IiMwNGI2MDEiIGQ9Ik0zMy4yNSAzMS42NTJBMTkuMDE1IDE5LjAxNSAwIDAgMCAzOCAxOS4wNkMzOCA4LjU0OSAyOS40NzggMCAxOSAwUzAgOC41NSAwIDE5LjA1OWMwIDQuODIzIDEuNzk1IDkuMjMzIDQuNzUgMTIuNTkzTDE4Ljk3NSA0NiAzMy4yNSAzMS42NTJ6Ij48L3BhdGg+PHBhdGggZmlsbD0iIzZBNkQ3NCIgZmlsbC1vcGFjaXR5PSIuNSIgZD0iTTI2Ljg2MiAzNy41bDQuNzE0LTQuNzdjMy44MjItMy41NzYgNS45MjQtOC40MTEgNS45MjQtMTMuNjJDMzcuNSA4Ljg0NyAyOS4yLjUgMTkgLjVTLjUgOC44NDguNSAxOS4xMWMwIDUuMjA5IDIuMTAyIDEwLjA0NCA1LjkxOSAxMy42MTRsNC43MTkgNC43NzZoMTUuNzI0ek0xOSAwYzEwLjQ5MyAwIDE5IDguNTI1IDE5IDE5LjA0MSAwIDUuNTA3LTIuMzQ4IDEwLjQ1NC02LjA3OSAxMy45MzJMMTkgNDYgNi4wNzkgMzIuOTczQzIuMzQ4IDI5LjQ5NSAwIDI0LjU0OCAwIDE5LjA0IDAgOC41MjUgOC41MDcgMCAxOSAweiI+PC9wYXRoPjwvZz48L3N2Zz4K" }, { name: "blueIcon", url: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzOCIgaGVpZ2h0PSI0NyIgdmlld0JveD0iMCAwIDM4IDQ3Ij48ZyBmaWxsPSJub25lIj48cGF0aCBmaWxsPSIjMEYxNjIxIiBmaWxsLW9wYWNpdHk9Ii40IiBkPSJNMTUgNDZjMCAuMzE3IDEuNzkuNTc0IDQgLjU3NHM0LS4yNTcgNC0uNTc0YzAtLjMxNy0xLjc5LS41NzQtNC0uNTc0cy00IC4yNTctNCAuNTc0eiI+PC9wYXRoPjxwYXRoIGZpbGw9IiMwMTgwYjYiIGQ9Ik0zMy4yNSAzMS42NTJBMTkuMDE1IDE5LjAxNSAwIDAgMCAzOCAxOS4wNkMzOCA4LjU0OSAyOS40NzggMCAxOSAwUzAgOC41NSAwIDE5LjA1OWMwIDQuODIzIDEuNzk1IDkuMjMzIDQuNzUgMTIuNTkzTDE4Ljk3NSA0NiAzMy4yNSAzMS42NTJ6Ij48L3BhdGg+PHBhdGggZmlsbD0iIzZBNkQ3NCIgZmlsbC1vcGFjaXR5PSIuNSIgZD0iTTI2Ljg2MiAzNy41bDQuNzE0LTQuNzdjMy44MjItMy41NzYgNS45MjQtOC40MTEgNS45MjQtMTMuNjJDMzcuNSA4Ljg0NyAyOS4yLjUgMTkgLjVTLjUgOC44NDguNSAxOS4xMWMwIDUuMjA5IDIuMTAyIDEwLjA0NCA1LjkxOSAxMy42MTRsNC43MTkgNC43NzZoMTUuNzI0ek0xOSAwYzEwLjQ5MyAwIDE5IDguNTI1IDE5IDE5LjA0MSAwIDUuNTA3LTIuMzQ4IDEwLjQ1NC02LjA3OSAxMy45MzJMMTkgNDYgNi4wNzkgMzIuOTczQzIuMzQ4IDI5LjQ5NSAwIDI0LjU0OCAwIDE5LjA0IDAgOC41MjUgOC41MDcgMCAxOSAweiI+PC9wYXRoPjwvZz48L3N2Zz4K" } ]; /** * Creates a new MapView for the HTMLCanvasElement of the given id. */ function initializeMapView(id: string): MapView { const canvas = document.getElementById(id) as HTMLCanvasElement; const map = new MapView({ canvas, theme: { extends: "resources/berlin_tilezen_base.json", styles: { // Specify the styling for the markers. geojson: [ { when: ["==", ["geometry-type"], "Point"], technique: "labeled-icon", imageTexture: ["get", "icon"], text: ["get", "text"], size: 15, priority: 1000, color: "black", iconMayOverlap: true, textMayOverlap: true, renderOrder: ["get", "renderOrder"], iconFadeTime: 0, textFadeTime: 0 } ] } }, target: new GeoCoordinates(52.52, 13.4), zoomLevel: 12 }); CopyrightElementHandler.install("copyrightNotice").attach(map); const controls = new MapControls(map); // Add an UI. const ui = new MapControlsUI(controls, { projectionSwitch: true, zoomLevel: "input" }); canvas.parentElement!.appendChild(ui.domElement); window.addEventListener("resize", () => { map.resize(window.innerWidth, window.innerHeight); }); map.update(); return map; } function handlePick( mapView: MapView, markersDataSource: FeaturesDataSource, x: number, y: number ): void { // Intersection test filtering the results by layer name to get only markers. const layerName = (markersDataSource.dataProvider() as GeoJsonDataProvider).name; const results = mapView.intersectMapObjects(x, y).filter(result => { return result.userData?.$layer === layerName; }); if (results.length === 0) { return; } const uuid = results[0].userData?.__mapViewUuid; if (uuid !== undefined) { const feature = new MapViewPointFeature([]); feature.uuid = uuid; markersDataSource.remove(feature); } } let markerId = 0; function attachClickEvents(mapView: MapView, markersDataSource: FeaturesDataSource) { mapView.canvas.addEventListener("click", event => { if (event.shiftKey) { const geo = mapView.getGeoCoordinatesAt(event.clientX, event.clientY); if (geo) { // Add a new marker to the data source at the click coordinates. markersDataSource.add( new MapViewPointFeature(geo.toGeoPoint() as number[], { text: markerId.toString(), id: markerId, icon: icons[markerId % icons.length].name, renderOrder: markerId }) ); markerId++; } } else if (event.ctrlKey) { handlePick(mapView, markersDataSource, event.pageX, event.pageY); } }); window.addEventListener("keypress", event => { if (event.key === "c") { markersDataSource.clear(); markerId = 0; } }); const instructions = ` Shift+Left Click to add a marker<br/>Ctrl+Left Click to remove it<br/> Press 'c' to clear the map.<br/>`; const message = document.createElement("div"); message.style.position = "absolute"; message.style.cssFloat = "right"; message.style.top = "10px"; message.style.right = "10px"; message.style.backgroundColor = "grey"; message.innerHTML = instructions; document.body.appendChild(message); } function attachDataSources(mapView: MapView) { const omvDataSource = new VectorTileDataSource({ baseUrl: "https://vector.hereapi.com/v2/vectortiles/base/mc", apiFormat: APIFormat.XYZOMV, styleSetName: "tilezen", maxDataLevel: 17, authenticationCode: apikey, authenticationMethod: { method: AuthenticationMethod.QueryString, name: "apikey" }, copyrightInfo }); mapView.addDataSource(omvDataSource); // Register the icon image referenced in the style. for (const { name, url } of icons) { mapView.userImageCache.addImage(name, url); } // Create a [[FeaturesDataSource]] for the markers. const markersDataSource = new FeaturesDataSource({ name: "geojson", styleSetName: "geojson", gatherFeatureAttributes: true }); mapView.addDataSource(markersDataSource); attachClickEvents(mapView, markersDataSource); } const mapView = initializeMapView("mapCanvas"); attachDataSources(mapView); }