Skip to content
This repository has been archived by the owner on Mar 8, 2023. It is now read-only.

Commit

Permalink
MINOR: Add dynamic markers example. (#1997)
Browse files Browse the repository at this point in the history
* MINOR: Add dynamic markers example.

* MINOR: Rename example.
  • Loading branch information
atomicsulfate committed Dec 4, 2020
1 parent 7624c25 commit f729dac
Showing 1 changed file with 192 additions and 0 deletions.
192 changes: 192 additions & 0 deletions @here/harp-examples/src/markers_dynamic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/*
* Copyright (C) 2017-2020 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);
}

0 comments on commit f729dac

Please sign in to comment.