選取您的 Cookie 偏好設定

我們使用提供自身網站和服務所需的基本 Cookie 和類似工具。我們使用效能 Cookie 收集匿名統計資料,以便了解客戶如何使用我們的網站並進行改進。基本 Cookie 無法停用,但可以按一下「自訂」或「拒絕」以拒絕效能 Cookie。

如果您同意,AWS 與經核准的第三方也會使用 Cookie 提供實用的網站功能、記住您的偏好設定,並顯示相關內容,包括相關廣告。若要接受或拒絕所有非必要 Cookie,請按一下「接受」或「拒絕」。若要進行更詳細的選擇,請按一下「自訂」。

搭配 Amazon Location Service 使用 Tangram

焦點模式
搭配 Amazon Location Service 使用 Tangram - Amazon Location Service

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

Tangram 是一種靈活的映射引擎,專為從向量圖磚即時轉譯 2D 和 3D 映射而設計。它可以與 Mapzen 設計的樣式和 Amazon Location Service Maps 提供的HERE動態磚搭配使用API。本指南說明如何在基本 HTML/ JavaScript 應用程式中將 Tangram 與 Amazon Location 整合,但在使用 React 和 Angular 等架構時,同樣也適用相同的程式庫和技術。

Tangram 建立在 Leaflet 之上,這是適用於行動互動地圖的開放原始碼 JavaScript 程式庫。這表示許多 Leaflet 相容外掛程式和控制項也適用於 Tangram。

使用來自 的映射時,為搭配 Tilezen 結構描述使用而建置的 Tangram 樣式在很大程度上與 Amazon Location 相容HERE。其中包含:

  • Bubble Wrap – 功能完整的尋路樣式,具有適用於興趣點的實用圖示

  • Cinnabar – 一般映射應用程式的經典外觀和首選

  • 補充 – 專為資料視覺化重疊所設計的極簡地圖樣式,其靈感來自 Stamen Design 的精實碳粉樣式

  • Tron – 探索 視覺化語言的規模轉換 TRON

  • Walkabout – 專注於戶外的樣式,非常適合健行或出遊

本指南說明如何使用名為 Bubble Wrap 的 Tangram 樣式,將 Tangram 與 Amazon Location 整合到基本 HTML/JavaScript application 中。此範例可作為 Amazon Location Service 範例儲存庫的一部分GitHub

雖然其他 Tangram 樣式最好搭配編碼地形資訊的光柵圖磚,但 Amazon Location 尚不支援此功能。

重要

下列教學課程中的 Tangram 樣式僅與以 VectorHereContrast樣式設定的 Amazon Location Map 資源相容。

建置應用程式:鷹架

應用程式是使用 的HTML頁面 JavaScript ,可在 Web 應用程式中建置地圖。建立HTML頁面 (index.html) 並建立映射的容器:

  • 輸入具有 映射iddiv 元素,將映射的維度套用至映射檢視。

  • 維度會從視埠繼承。

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

建置應用程式:新增相依性

新增下列相依性:

  • 單張及其相關聯的 CSS。

  • Tangram。

  • AWS SDK 適用於 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>

這會建立具有必要先決條件的空白頁面。下一步會引導您撰寫應用程式的 JavaScript 程式碼。

建置應用程式:組態

若要使用 資源和憑證設定應用程式:

  1. 輸入資源的名稱和識別碼。

    // 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. 使用您在使用地圖 - 步驟 2,設定身分驗證 中建立的未驗證身分集區,來即時化憑證提供者。由於這會在正常AWSSDK工作流程之外使用憑證,因此工作階段會在一小時後過期。

    // 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 允許您覆寫用來擷取動態磚的 URL(s),但它不包括攔截請求的功能,以便可以簽署。

    若要解決此問題,請覆寫 sources.mapzen.url 以使用合成主機名稱 指向 Amazon Locationamazon.location,該名稱將由服務工作者 處理。以下是使用 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, }, }, };

建置應用程式:請求轉換

若要註冊和初始化服務工作者,請在初始化映射之前建立要呼叫的registerServiceWorker函數。這會註冊在名為控制 的 服務工作者sw.js的個別檔案中提供的 JavaScript 程式碼index.html

憑證會從 Amazon Cognito 載入,並與區域一起傳遞給服務工作者,以提供使用 Signature 第 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"); } }

中的服務工作者實作會sw.js監聽message事件,以接收憑證和區域組態變更。它也可以透過聆聽fetch事件來充當代理伺服器。針對amazon.location合成主機名稱fetch的事件會重新寫入,以鎖定適當的 Amazon 位置API,並使用 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)); });

若要自動續約憑證,並在憑證過期之前將其傳送給服務工作者,請在 中使用下列函數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()); }

建置應用程式:映射初始化

若要讓地圖在頁面載入後顯示,您必須初始化地圖。您可以選擇調整初始映射位置、新增其他控制項和覆蓋資料。

注意

您必須為應用程式或文件上使用的每個資料提供者提供文字標記或文字屬性。屬性字串包含在 sources.esri.attributionsources.here.attributionsource.grabmaptiles.attribution金鑰下的樣式描述符回應中。

由於 Tangram 不會請求這些資源,並且只與來自 的映射相容HERE,因此請使用「© 2020HERE」。將 Amazon Location 資源與資料提供者 搭配使用時,請務必閱讀服務條款與條件

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

執行應用程式

若要執行此範例,您可以:

  • 使用支援 的主機HTTPS,

  • 使用本機 Web 伺服器來遵守服務工作者安全限制。

若要使用本機 Web 伺服器,您可以使用 npx,因為它是 Node.js 的一部分。您可以在npx serveindex.html和 相同的目錄中使用 sw.js。這可在 localhost:5000 上提供應用程式。

以下是 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>

以下是 sw.js 檔案:

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

此範例可作為 Amazon Location Service 範例儲存庫的一部分GitHub

隱私權網站條款Cookie 偏好設定
© 2025, Amazon Web Services, Inc.或其附屬公司。保留所有權利。