Tangram mit Amazon Location Service verwenden - Amazon Location Service

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Tangram mit Amazon Location Service verwenden

Tangram ist eine flexible Mapping-Engine, die für das Echtzeit-Rendern von 2D- und 3D-Karten aus Vektorkacheln entwickelt wurde. Es kann mit von MapZen entworfenen Stilen und den von Amazon Location Service Maps bereitgestellten HERE Kacheln verwendet werden. API In diesem Handbuch wird beschrieben, wie Tangram mit Amazon Location in eine grundlegende HTML JavaScript /-Anwendung integriert wird. Dieselben Bibliotheken und Techniken gelten auch für die Verwendung von Frameworks wie React und Angular.

Tangram basiert auf Leaflet, einer JavaScript Open-Source-Bibliothek für mobilfreundliche interaktive Karten. Das bedeutet, dass viele Leaflet-kompatible Plugins und Steuerungen auch mit Tangram funktionieren.

Tangram-Stile, die für das Tilezen-Schema erstellt wurden, sind weitgehend kompatibel mit Amazon Location, wenn Karten von verwendet werden. HERE Dazu zählen:

  • Bubble Wrap — Ein Orientierungsstil mit vollem Funktionsumfang und hilfreichen Symbolen für Sehenswürdigkeiten

  • Zinnober — Ein klassisches Design und ein Muss für allgemeine Kartenanwendungen

  • Refill — Ein minimalistischer Kartenstil für Datenvisualisierungs-Overlays, inspiriert vom wegweisenden Toner-Stil von Stamen Design

  • Tron — Eine Untersuchung von Maßstabstransformationen in der Bildsprache von TRON

  • Walkabout — Ein Outdoor-Style, der sich perfekt zum Wandern oder für unterwegs eignet

In diesem Handbuch wird beschrieben, wie Sie Tangram mit Amazon Location in eine einfache HTML JavaScript /-Anwendung integrieren, die den Tangram-Stil namens Bubble Wrap verwendet. Dieses Beispiel ist als Teil des Amazon Location Service Samples Repository unter verfügbar GitHub.

Während andere Tangram-Styles am besten von Raster-Kacheln begleitet werden, die Geländeinformationen kodieren, wird diese Funktion von Amazon Location noch nicht unterstützt.

Wichtig

Die Tangram-Stile in der folgenden Anleitung sind nur mit Amazon Location Map-Ressourcen kompatibel, die mit dem VectorHereContrast Stil konfiguriert wurden.

Erstellung der Anwendung: Scaffolding

Die Anwendung ist eine HTML Seite JavaScript zum Erstellen der Karte in Ihrer Webanwendung. Erstellen Sie eine HTML Seite (index.html) und erstellen Sie den Container der Karte:

  • Geben Sie ein div Element mit id einer OF-Karte ein, um die Abmessungen der Karte auf die Kartenansicht anzuwenden.

  • Die Abmessungen werden aus dem Viewport übernommen.

<html> <head> <style> body { margin: 0; } #map { height: 100vh; /* 100% of viewport height */ } </style> </head> <body> <!-- map container --> <div id="map" /> </body> </html>

Die Anwendung erstellen: Abhängigkeiten hinzufügen

Fügen Sie die folgenden Abhängigkeiten hinzu:

  • Flugblatt und dazugehörige CSS Informationen.

  • Tangram.

  • AWSSDKfür JavaScript.

<!-- CSS dependencies --> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin="" /> <!-- JavaScript dependencies --> <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script> <script src="https://unpkg.com/tangram"></script> <script src="https://sdk.amazonaws.com/js/aws-sdk-2.784.0.min.js"></script> <script> // application-specific code </script>

Dadurch wird eine leere Seite mit den erforderlichen Voraussetzungen erstellt. Der nächste Schritt führt Sie durch das Schreiben des JavaScript Codes für Ihre Anwendung.

Die Anwendung erstellen: Konfiguration

So konfigurieren Sie Ihre Anwendung mit Ihren Ressourcen und Anmeldeinformationen:

  1. Geben Sie die Namen und Kennungen Ihrer Ressourcen ein.

    // Cognito Identity Pool ID const identityPoolId = "us-east-1:54f2ba88-9390-498d-aaa5-0d97fb7ca3bd"; // Amazon Location Service map name; must be HERE-backed const mapName = "TangramExampleMap";
  2. Instanziieren Sie einen Anmeldeinformationsanbieter mithilfe des nicht authentifizierten Identitätspools, den Sie unter Karten verwenden — Schritt 2, Authentifizierung einrichten erstellt haben. Da dabei Anmeldeinformationen außerhalb des normalen Workflows verwendet werden, AWS SDK laufen Sitzungen nach einer Stunde ab.

    // extract the region from the Identity Pool ID; this will be used for both Amazon Cognito and Amazon Location AWS.config.region = identityPoolId.split(":", 1)[0]; // instantiate a Cognito-backed credential provider const credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: identityPoolId, });
  3. Tangram ermöglicht es Ihnen zwar, die zum Abrufen von Kacheln verwendeten URL (n) zu überschreiben, bietet jedoch nicht die Möglichkeit, Anfragen abzufangen, sodass sie signiert werden können.

    Um dies zu umgehen, können sources.mapzen.url Sie überschreiben, indem Sie mithilfe eines synthetischen Hostnamens auf Amazon Location verweisenamazon.location, der von einem Servicemitarbeiter verwaltet wird. Im Folgenden finden Sie ein Beispiel für die Szenenkonfiguration mit Bubble Wrap:

    const scene = { import: [ // Bubble Wrap style "https://www.nextzen.org/carto/bubble-wrap-style/10/bubble-wrap-style.zip", "https://www.nextzen.org/carto/bubble-wrap-style/10/themes/label-7.zip", "https://www.nextzen.org/carto/bubble-wrap-style/10/themes/bubble-wrap-road-shields-usa.zip", "https://www.nextzen.org/carto/bubble-wrap-style/10/themes/bubble-wrap-road-shields-international.zip", ], // override values beneath the `sources` key in the style above sources: { mapzen: { // point at Amazon Location using a synthetic URL, which will be handled by the service // worker url: `https://amazon.location/${mapName}/{z}/{x}/{y}`, }, // effectively disable raster tiles containing encoded normals normals: { max_zoom: 0, }, "normals-elevation": { max_zoom: 0, }, }, };

Die Anwendung erstellen: Transformation anfordern

Um den Service Worker zu registrieren und zu initialisieren, erstellen Sie eine registerServiceWorker Funktion, die aufgerufen werden soll, bevor die Map initialisiert wird. Dadurch wird der JavaScript Code registriert, der in einer separaten Datei namens Service Worker sw.js Controlling bereitgestellt wird. index.html

Anmeldeinformationen werden von Amazon Cognito geladen und zusammen mit der Region an den Servicemitarbeiter weitergegeben, um Informationen zum Signieren von Kachelanfragen mit Signature Version 4 bereitzustellen.

/** * Register a service worker that will rewrite and sign requests using Signature Version 4. */ async function registerServiceWorker() { if ("serviceWorker" in navigator) { try { const reg = await navigator.serviceWorker.register("./sw.js"); // refresh credentials from Amazon Cognito await credentials.refreshPromise(); await reg.active.ready; if (navigator.serviceWorker.controller == null) { // trigger a navigate event to active the controller for this page window.location.reload(); } // pass credentials to the service worker reg.active.postMessage({ credentials: { accessKeyId: credentials.accessKeyId, secretAccessKey: credentials.secretAccessKey, sessionToken: credentials.sessionToken, }, region: AWS.config.region, }); } catch (error) { console.error("Service worker registration failed:", error); } } else { console.warn("Service worker support is required for this example"); } }

Die Service Worker-Implementierung in sw.js wartet auf message Ereignisse, um Änderungen an den Anmeldeinformationen und der Regionskonfiguration zu erfassen. Sie fungiert auch als Proxyserver, indem sie auf Ereignisse wartetfetch. fetchEreignisse, die auf den amazon.location synthetischen Hostnamen abzielen, werden so umgeschrieben, dass sie auf den entsprechenden Amazon-Standort abzielen, API und mit Amplify Cores signiert. Signer

// sw.js self.importScripts( "https://unpkg.com/@aws-amplify/core@3.7.0/dist/aws-amplify-core.min.js" ); const { Signer } = aws_amplify_core; let credentials; let region; self.addEventListener("install", (event) => { // install immediately event.waitUntil(self.skipWaiting()); }); self.addEventListener("activate", (event) => { // control clients ASAP event.waitUntil(self.clients.claim()); }); self.addEventListener("message", (event) => { const { data: { credentials: newCredentials, region: newRegion }, } = event; if (newCredentials != null) { credentials = newCredentials; } if (newRegion != null) { region = newRegion; } }); async function signedFetch(request) { const url = new URL(request.url); const path = url.pathname.slice(1).split("/"); // update URL to point to Amazon Location url.pathname = `/maps/v0/maps/${path[0]}/tiles/${path.slice(1).join("/")}`; url.host = `maps.geo.${region}.amazonaws.com`; // strip params (Tangram generates an empty api_key param) url.search = ""; const signed = Signer.signUrl(url.toString(), { access_key: credentials.accessKeyId, secret_key: credentials.secretAccessKey, session_token: credentials.sessionToken, }); return fetch(signed); } self.addEventListener("fetch", (event) => { const { request } = event; // match the synthetic hostname we're telling Tangram to use if (request.url.includes("amazon.location")) { return event.respondWith(signedFetch(request)); } // fetch normally return event.respondWith(fetch(request)); });

Um Anmeldeinformationen automatisch zu erneuern und sie vor Ablauf an den Servicemitarbeiter zu senden, verwenden Sie die folgende Funktion innerhalb: index.html

async function refreshCredentials() { await credentials.refreshPromise(); if ("serviceWorker" in navigator) { const controller = navigator.serviceWorker.controller; controller.postMessage({ credentials: { accessKeyId: credentials.accessKeyId, secretAccessKey: credentials.secretAccessKey, sessionToken: credentials.sessionToken, }, }); } else { console.warn("Service worker support is required for this example."); } // schedule the next credential refresh when they're about to expire setTimeout(refreshCredentials, credentials.expireTime - new Date()); }

Die Anwendung erstellen: Initialisierung der Map

Damit die Map nach dem Laden der Seite angezeigt wird, müssen Sie die Map initialisieren. Sie haben die Möglichkeit, die ursprüngliche Kartenposition anzupassen, zusätzliche Steuerelemente hinzuzufügen und Daten zu überlagern.

Anmerkung

Sie müssen für jeden Datenanbieter, den Sie verwenden, entweder in Ihrer Anwendung oder in Ihrer Dokumentation eine Wortmarke oder eine Textzuweisung angeben. Zuordnungszeichenfolgen sind in der Antwort auf den Stildeskriptor unter den Tasten sources.esri.attributionsources.here.attribution, und enthalten. source.grabmaptiles.attribution

Da Tangram diese Ressourcen nicht anfordert und nur mit Karten von kompatibel istHERE, verwende „© 2020“. HERE Wenn Sie Amazon-Standortressourcen mit Datenanbietern verwenden, lesen Sie unbedingt die Servicebedingungen.

/** * Initialize a map. */ async function initializeMap() { // register the service worker to handle requests to https://amazon.location await registerServiceWorker(); // Initialize the map const map = L.map("map").setView([49.2819, -123.1187], 10); Tangram.leafletLayer({ scene, }).addTo(map); map.attributionControl.setPrefix(""); map.attributionControl.addAttribution("© 2020 HERE"); } initializeMap();

Die Anwendung wird ausgeführt

Um dieses Beispiel auszuführen, können Sie:

  • Verwenden Sie einen Host, der unterstütztHTTPS,

  • Verwenden Sie einen lokalen Webserver, um die Sicherheitseinschränkungen für Servicemitarbeiter einzuhalten.

Um einen lokalen Webserver zu verwenden, können Sie npx verwenden, da er als Teil von Node.js installiert ist. Sie können es npx serve aus demselben Verzeichnis wie index.html und sw.js verwenden. Dies dient der Anwendung auf localhost:5000.

Das Folgende ist die Datei: index.html

<!-- index.html --> <html> <head> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin="" /> <style> body { margin: 0; } #map { height: 100vh; } </style> </head> <body> <div id="map" /> <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script> <script src="https://unpkg.com/tangram"></script> <script src="https://sdk.amazonaws.com/js/aws-sdk-2.784.0.min.js"></script> <script> // configuration // Cognito Identity Pool ID const identityPoolId = "<Identity Pool ID>"; // Amazon Location Service Map name; must be HERE-backed const mapName = "<Map name>"; AWS.config.region = identityPoolId.split(":")[0]; // instantiate a credential provider credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: identityPoolId, }); const scene = { import: [ // Bubble Wrap style "https://www.nextzen.org/carto/bubble-wrap-style/10/bubble-wrap-style.zip", "https://www.nextzen.org/carto/bubble-wrap-style/10/themes/label-7.zip", "https://www.nextzen.org/carto/bubble-wrap-style/10/themes/bubble-wrap-road-shields-usa.zip", "https://www.nextzen.org/carto/bubble-wrap-style/10/themes/bubble-wrap-road-shields-international.zip", ], // override values beneath the `sources` key in the style above sources: { mapzen: { // point at Amazon Location using a synthetic URL, which will be handled by the service // worker url: `https://amazon.location/${mapName}/{z}/{x}/{y}`, }, // effectively disable raster tiles containing encoded normals normals: { max_zoom: 0, }, "normals-elevation": { max_zoom: 0, }, }, }; /** * Register a service worker that will rewrite and sign requests using Signature Version 4. */ async function registerServiceWorker() { if ("serviceWorker" in navigator) { try { const reg = await navigator.serviceWorker.register("./sw.js"); // refresh credentials from Amazon Cognito await credentials.refreshPromise(); await reg.active.ready; if (navigator.serviceWorker.controller == null) { // trigger a navigate event to active the controller for this page window.location.reload(); } // pass credentials to the service worker reg.active.postMessage({ credentials: { accessKeyId: credentials.accessKeyId, secretAccessKey: credentials.secretAccessKey, sessionToken: credentials.sessionToken, }, region: AWS.config.region, }); } catch (error) { console.error("Service worker registration failed:", error); } } else { console.warn("Service Worker support is required for this example"); } } /** * Initialize a map. */ async function initializeMap() { // register the service worker to handle requests to https://amazon.location await registerServiceWorker(); // Initialize the map const map = L.map("map").setView([49.2819, -123.1187], 10); Tangram.leafletLayer({ scene, }).addTo(map); map.attributionControl.setPrefix(""); map.attributionControl.addAttribution("© 2020 HERE"); } initializeMap(); </script> </body> </html>

Das Folgende ist die sw.js Datei:

// sw.js self.importScripts( "https://unpkg.com/@aws-amplify/core@3.7.0/dist/aws-amplify-core.min.js" ); const { Signer } = aws_amplify_core; let credentials; let region; self.addEventListener("install", (event) => { // install immediately event.waitUntil(self.skipWaiting()); }); self.addEventListener("activate", (event) => { // control clients ASAP event.waitUntil(self.clients.claim()); }); self.addEventListener("message", (event) => { const { data: { credentials: newCredentials, region: newRegion }, } = event; if (newCredentials != null) { credentials = newCredentials; } if (newRegion != null) { region = newRegion; } }); async function signedFetch(request) { const url = new URL(request.url); const path = url.pathname.slice(1).split("/"); // update URL to point to Amazon Location url.pathname = `/maps/v0/maps/${path[0]}/tiles/${path.slice(1).join("/")}`; url.host = `maps.geo.${region}.amazonaws.com`; // strip params (Tangram generates an empty api_key param) url.search = ""; const signed = Signer.signUrl(url.toString(), { access_key: credentials.accessKeyId, secret_key: credentials.secretAccessKey, session_token: credentials.sessionToken, }); return fetch(signed); } self.addEventListener("fetch", (event) => { const { request } = event; // match the synthetic hostname we're telling Tangram to use if (request.url.includes("amazon.location")) { return event.respondWith(signedFetch(request)); } // fetch normally return event.respondWith(fetch(request)); });

Dieses Beispiel ist als Teil des Amazon Location Service Samples Repository unter verfügbar GitHub.