Usare Tangram con Amazon Location Service - Servizio di posizione Amazon

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Usare Tangram con Amazon Location Service

Tangram è un motore di mappatura flessibile, progettato per il rendering in tempo reale di mappe 2D e 3D da riquadri vettoriali. Può essere utilizzato con gli stili progettati da Mapzen e i riquadri HERE forniti dall'API Maps di Amazon Location Service. Questa guida descrive come integrare Tangram con Amazon Location all'interno di un'JavaScript applicazione HTML/ di base, sebbene le stesse librerie e tecniche si applichino anche quando si utilizzano framework come React e Angular.

Tangram è basato su Leaflet, una libreria open source per mappe interattive ottimizzate per dispositivi mobili. JavaScript Ciò significa che molti plugin e controlli compatibili con Leaflet funzionano anche con Tangram.

Gli stili Tangram creati per funzionare con lo schema Tilezen sono ampiamente compatibili con Amazon Location quando si utilizzano mappe di HERE. Ciò include:

  • Bubble Wrap: uno stile di orientamento completo con icone utili per i punti di interesse

  • Cinnabar: un look classico e ideale per le applicazioni di mappatura generali

  • Refill: uno stile di mappa minimalista progettato per sovrapposizioni di visualizzazione dei dati, ispirato allo stile fondamentale Toner di Stamen Design

  • Tron — Un'esplorazione delle trasformazioni di scala nel linguaggio visivo di TRON

  • Walkabout: uno stile incentrato sulle attività all'aperto, perfetto per le escursioni o per uscire

Questa guida descrive come integrare Tangram con Amazon Location all'interno di un'JavaScript applicazione HTML/HTML di base utilizzando lo stile Tangram chiamato Bubble Wrap. Questo esempio è disponibile come parte dell'archivio di esempi di Amazon Location Service su GitHub.

Sebbene altri stili Tangram siano meglio accompagnati da riquadri raster, che codificano le informazioni sul terreno, questa funzionalità non è ancora supportata da Amazon Location.

Importante

Gli stili Tangram illustrati nel seguente tutorial sono compatibili solo con le risorse della mappa di Amazon Location configurate con lo VectorHereContrast stile.

Creazione dell'applicazione: Scaffolding

L'applicazione è una pagina HTML con JavaScript cui creare la mappa sulla tua applicazione web. Crea una pagina HTML (index.html) e crea il contenitore della mappa:

  • Inserisci un div elemento con una id mappa per applicare le dimensioni della mappa alla visualizzazione della mappa.

  • Le dimensioni vengono ereditate dalla finestra.

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

Creazione dell'applicazione: aggiunta di dipendenze

Aggiungi le seguenti dipendenze:

  • Leaflet e il relativo CSS associato.

  • Tangram.

  • SDK AWS per 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>

Questo crea una pagina vuota con i prerequisiti necessari. Il passaggio successivo ti guida nella scrittura del JavaScript codice per la tua applicazione.

Creazione dell'applicazione: configurazione

Per configurare l'applicazione con le tue risorse e credenziali:

  1. Inserisci i nomi e gli identificatori delle tue risorse.

    // 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. Crea un'istanza di un provider di credenziali utilizzando il pool di identità non autenticato che hai creato in Uso delle mappe - Passaggio 2, Configurazione dell'autenticazione. Poiché utilizza credenziali al di fuori del normale flusso di lavoro dell'SDK AWS, le sessioni scadono dopo un'ora.

    // 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. Sebbene Tangram consenta di sovrascrivere gli URL utilizzati per recuperare i riquadri, non include la possibilità di intercettare le richieste in modo che possano essere firmate.

    Per ovviare a questo problema, esegui l'override in modo da sources.mapzen.url puntare ad Amazon Location utilizzando un nome host sinteticoamazon.location, che verrà gestito da un addetto all'assistenza. Di seguito è riportato un esempio di configurazione della scena con 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, }, }, };

Creazione dell'applicazione: richiedi la trasformazione

Per registrare e inizializzare l'addetto all'assistenza, crea una registerServiceWorker funzione da chiamare prima dell'inizializzazione della mappa. Questo registra il JavaScript codice fornito in un file separato chiamato service sw.js worker control. index.html

Le credenziali vengono caricate da Amazon Cognito e passate al service worker insieme alla Regione per fornire informazioni per firmare le richieste di tile con Signature Version 4.

/** * 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"); } }

L'implementazione di Service Worker in sw.js ascolta message gli eventi per rilevare le modifiche alle credenziali e alla configurazione della regione. Funziona anche come server proxy ascoltando gli fetch eventi. fetchgli eventi che hanno come target il nome host amazon.location sintetico verranno riscritti per indirizzare l'API Amazon Location appropriata e firmati utilizzando Amplify Core. 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)); });

Per rinnovare automaticamente le credenziali e inviarle all'addetto all'assistenza prima della scadenza, utilizza la seguente funzione all'interno di: 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()); }

Creazione dell'applicazione: inizializzazione della mappa

Affinché la mappa venga visualizzata dopo il caricamento della pagina, è necessario inizializzare la mappa. È possibile modificare la posizione iniziale della mappa, aggiungere controlli aggiuntivi e sovrapporre i dati.

Nota

È necessario fornire un marchio denominativo o un'attribuzione di testo per ogni fornitore di dati che si utilizza, nell'applicazione o nella documentazione. Le stringhe di attribuzione sono incluse nella risposta del descrittore di stile sotto i tastisources.esri.attribution, sources.here.attribution e. source.grabmaptiles.attribution

Poiché Tangram non richiede queste risorse ed è compatibile solo con le mappe di HERE, usa «© 2020 HERE». Quando utilizzi le risorse di Amazon Location con fornitori di dati, assicurati di leggere i termini e le condizioni del servizio.

/** * 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();

Esecuzione dell'applicazione

Per eseguire questo esempio, puoi:

  • Usa un host che supporti HTTPS,

  • Utilizza un server Web locale per rispettare le restrizioni di sicurezza degli addetti all'assistenza.

Per utilizzare un server web locale, puoi usare npx, perché è installato come parte di Node.js. È possibile utilizzare npx serve dall'interno della stessa directory di index.html esw.js. Questo serve l'applicazione su localhost:5000.

Il seguente è il file: 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>

Il seguente è il sw.js file:

// 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)); });

Questo esempio è disponibile come parte dell'archivio di esempi di Amazon Location Service su GitHub.