KmlLayer
會將 KML 和 GeoRSS 元素算繪成 Maps JavaScript API 圖塊疊加層。
總覽
Maps JavaScript API 支援顯示地理資訊的 KML 和 GeoRSS 資料格式。這些資料格式使用 KmlLayer
物件顯示在地圖上,該物件的建構函式接受可公開存取的 KML 或 GeoRSS 檔案網址。
注意:在 Maps JavaScript API 中產生 KML 疊加層的 KmlLayer
類別,會以 Google 代管的服務擷取和剖析 KML 檔案,並進行算繪。因此,只有當 KML 檔案代管在無需驗證即可公開存取的網址時,才能顯示這些檔案。
如果您需要存取私人檔案、精確控制快取,或是將瀏覽器可視區域做為查詢參數傳送至地理空間資料伺服器,建議使用資料層,而非 KmlLayer
。這會引導使用者的瀏覽器直接向您的網路伺服器要求資源。
Maps JavaScript API 會將提供的地理 XML 資料轉換成 KML 表示法,並使用 Maps JavaScript API 圖塊疊加層顯示在地圖上。這個 KML 不僅外觀與 Maps JavaScript API 疊加層元素十分相似,兩者的某些行為也十分雷同。舉例來說,KML <Placemark>
與 GeoRSS point
元素都會算繪為標記,<LineString>
元素會算繪為折線,而 <Polygon>
元素則會算繪為多邊形。同樣地,<GroundOverlay>
元素在地圖上會算繪為矩形圖片。但請注意,這些物件不是 Maps JavaScript API Markers
、Polylines
、Polygons
或 GroundOverlays
,而是會算繪為地圖上的單一物件。
設定 KmlLayer
物件的 map
屬性後,物件就會顯示在地圖上。您可以呼叫 setMap()
並傳遞 null
,將該物件從地圖上移除。KmlLayer
物件會針對地圖的特定範圍自動擷取適合的地圖項目,藉此管理這些子元素的算繪作業。範圍會產生變化時,目前可視區域內的地圖項目會自動算繪。
KmlLayer
內的元件是隨需算繪,因此您可以運用圖層輕鬆管理數千個標記、折線及多邊形的算繪作業。請注意,雖然每個構成物件所提供的點擊事件會針對各物件本身傳回資料,但您無法直接存取這些構成物件。
KML 圖層選項
KmlLayer()
建構函式會視需要傳遞數個 KmlLayerOptions
:
map
指定要算繪KmlLayer
的Map
。在setMap()
方法中將此值設定為null
,即可隱藏KmlLayer
。preserveViewport
指定顯示圖層時,不應根據KmlLayer
的內容範圍調整地圖。根據預設,顯示KmlLayer
時,地圖會縮放並調整位置以顯示圖層的完整內容。suppressInfoWindows
表示KmlLayer
內的可點選地圖項目不應觸發InfoWindow
物件顯示。
此外,經過算繪後,KmlLayer
會包含不可變更的 metadata
屬性,該屬性的 KmlLayerMetadata
物件常值中內含圖層的名稱、說明、程式碼片段及作者。您可以使用 getMetadata()
方法檢查此資訊。算繪 KmlLayer
物件時需要與外部伺服器進行非同步通訊,因此建議您監聽 metadata_changed
事件,事件會表示已經填入屬性。
以下範例是根據指定的 GeoRSS 動態饋給來建構 KmlLayer
:
TypeScript
function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 4, center: { lat: 49.496675, lng: -102.65625 }, } ); const georssLayer = new google.maps.KmlLayer({ url: "http://api.flickr.com/services/feeds/geo/?g=322338@N20&lang=en-us&format=feed-georss", }); georssLayer.setMap(map); } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
function initMap() { const map = new google.maps.Map(document.getElementById("map"), { zoom: 4, center: { lat: 49.496675, lng: -102.65625 }, }); const georssLayer = new google.maps.KmlLayer({ url: "http://api.flickr.com/services/feeds/geo/?g=322338@N20&lang=en-us&format=feed-georss", }); georssLayer.setMap(map); } window.initMap = initMap;
CSS
/* * Always set the map height explicitly to define the size of the div element * that contains the map. */ #map { height: 100%; } /* * Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; }
HTML
<html> <head> <title>GeoRSS Layers</title> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="map"></div> <!-- The `defer` attribute causes the script to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly" defer ></script> </body> </html>
測試範例
以下範例是根據指定的 KML 動態饋給來建構 KmlLayer
:
TypeScript
function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 11, center: { lat: 41.876, lng: -87.624 }, } ); const ctaLayer = new google.maps.KmlLayer({ url: "https://googlearchive.github.io/js-v2-samples/ggeoxml/cta.kml", map: map, }); } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
function initMap() { const map = new google.maps.Map(document.getElementById("map"), { zoom: 11, center: { lat: 41.876, lng: -87.624 }, }); const ctaLayer = new google.maps.KmlLayer({ url: "https://googlearchive.github.io/js-v2-samples/ggeoxml/cta.kml", map: map, }); } window.initMap = initMap;
CSS
/* * Always set the map height explicitly to define the size of the div element * that contains the map. */ #map { height: 100%; } /* * Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; }
HTML
<html> <head> <title>KML Layers</title> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="map"></div> <!-- The `defer` attribute causes the script to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly" defer ></script> </body> </html>
測試範例
KML 地圖項目詳細資料
KML 可能包含大量地圖項目,因此您無法直接從 KmlLayer
物件存取地圖項目資料。不過,顯示地圖項目時,系統會進行算繪,使地圖項目看起來像是可點選的 Maps JavaScript API 疊加層。根據預設,點選個別地圖項目時,系統會顯示 <title>
,其中包含與指定地圖項目相關的 KML <title>
和 <description>
資訊。此外,點選 KML 地圖項目會產生 KmlMouseEvent
並傳遞下列資訊:
position
表示錨定此 KML 地圖項目InfoWindow
的經緯度座標。這個位置通常是多邊形、折線和地面疊加層的點選位置,但對標記而言,則是實際起點。pixelOffset
表示從上方的position
到錨定InfoWindow
「尾端」位置的偏移值。對多邊形物件而言,此偏移值通常是0,0
,但對標記而言,還必須包含標記的高度。featureData
包含KmlFeatureData
的 JSON 結構。
以下顯示範例 KmlFeatureData
物件:
{ author: { email: "nobody@google.com", name: "Mr Nobody", uri: "http://example.com" }, description: "description", id: "id", infoWindowHtml: "html", name: "name", snippet: "snippet" }
以下範例顯示地圖項目經點選時,側邊 <div>
內的 KML 地圖項目 <Description>
文字:
TypeScript
function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 12, center: { lat: 37.06, lng: -95.68 }, } ); const kmlLayer = new google.maps.KmlLayer({ url: "https://raw.githubusercontent.com/googlearchive/kml-samples/gh-pages/kml/Placemark/placemark.kml", suppressInfoWindows: true, map: map, }); kmlLayer.addListener("click", (kmlEvent) => { const text = kmlEvent.featureData.description; showInContentWindow(text); }); function showInContentWindow(text: string) { const sidebar = document.getElementById("sidebar") as HTMLElement; sidebar.innerHTML = text; } } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
function initMap() { const map = new google.maps.Map(document.getElementById("map"), { zoom: 12, center: { lat: 37.06, lng: -95.68 }, }); const kmlLayer = new google.maps.KmlLayer({ url: "https://raw.githubusercontent.com/googlearchive/kml-samples/gh-pages/kml/Placemark/placemark.kml", suppressInfoWindows: true, map: map, }); kmlLayer.addListener("click", (kmlEvent) => { const text = kmlEvent.featureData.description; showInContentWindow(text); }); function showInContentWindow(text) { const sidebar = document.getElementById("sidebar"); sidebar.innerHTML = text; } } window.initMap = initMap;
CSS
/* Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; } #container { height: 100%; display: flex; } #sidebar { flex-basis: 15rem; flex-grow: 1; padding: 1rem; max-width: 30rem; height: 100%; box-sizing: border-box; overflow: auto; } #map { flex-basis: 0; flex-grow: 4; height: 100%; }
HTML
<html> <head> <title>KML Feature Details</title> <link rel="stylesheet" type="text/css" href="./style.css" /> <script type="module" src="./index.js"></script> </head> <body> <div id="container"> <div id="map"></div> <div id="sidebar"></div> </div> <!-- The `defer` attribute causes the script to execute after the full HTML document has been parsed. For non-blocking uses, avoiding race conditions, and consistent behavior across browsers, consider loading using Promises. See https://developers.google.com/maps/documentation/javascript/load-maps-js-api for more information. --> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly" defer ></script> </body> </html>
測試範例
KML 算繪的大小和複雜度限制
Maps JavaScript API 會限制所載入 KML 檔案的大小和複雜度。以下摘要列出目前的限制:
注意:這些限制隨時可能有所變動。
- 可擷取檔案大小上限 (原始 KML、原始 GeoRSS 或壓縮過的 KMZ)
- 3 MB
- 未壓縮 KML 檔案大小上限
- 10 MB
- KMZ 檔案中未壓縮圖片檔大小上限
- 每個檔案 500 KB
- 網路連結數量上限
- 10
- 整份文件的地圖項目總數上限
- 1,000
- KML 圖層數量
- 單一 Google 地圖可顯示的 KML 圖層數量有上限。如果超過此上限,地圖上就不會顯示您的任何圖層,且網路瀏覽器的 JavaScript 控制台中會顯示錯誤訊息。這個上限取決於兩項因素,即已建立的
KmlLayer
類別數量,以及用於建立這些圖層的所有網址總長度。您建立的所有新KmlLayer
都會佔圖層上限的一部分,而 KML 檔案載入來源的網址長度也會佔另一部分。因此,可新增的圖層數量會因應用程式而異。平均來說,您應該可以載入 10 到 20 個圖層,而不會達到上限。如果您仍達到上限,請使用網址縮短工具縮短 KML 網址。您也可以建立單一 KML 檔案,在其中納入指向個別 KML 網址的 NetworkLink。
效能和快取注意事項
Google 的伺服器會暫時快取 KML 檔案,以降低伺服器的負載。這也會在使用者點選、平移和縮放地圖時,為 KML 檔案提供適當區隔以有效利用空間呈現方式,進而改善使用者體驗。
為獲得最佳成效,建議您:
- 在 KML 中使用適當的
<expires>
標記。
KmlLayer
決定如何快取 KML 檔案時,「不會」使用 HTTP 標頭。 - 請勿在要求時動態產生檔案。
請改為在有需要前就產生檔案,並以靜態方式提供。如果伺服器需要較長的時間來傳輸 KML 檔案,KmlLayer
可能無法顯示。 - 除非您明確知道檔案已更新,否則請勿嘗試略過快取。
如果網站使用者突然增加,且您提供大型的 KML 檔案,則一律略過快取 (例如透過附加隨機號碼或使用者的時鐘時間做為查詢參數) 會導致伺服器過載。
此外,如果使用者的時鐘不正確,且<expires>
標記未正確設定,還可能會導致快取為使用者提供過時的資料。
請改為使用獨立的新修訂版本編號發布更新後的靜態檔案,然後使用伺服器端程式碼,將傳送至KmlLayer
的網址動態更新為目前版本。 - 將您的 KML 檔案變更頻率限制為每分鐘一次。
如果所有檔案的總大小 (未壓縮) 超過 1 MB,則將變更頻率限制為每 5 分鐘一次。 - 使用地理空間資料伺服器時,請避免使用查詢參數來限制圖層的可視區域。
您可以改為使用bounds_changed
事件來限制地圖可視區域。系統只會向使用者傳送可自動顯示的地圖項目。
如果地理空間資料伺服器中有大量資料,建議您改用資料層。 - 使用地理空間資料伺服器時,請針對要允許使用者切換的每個地圖項目群組使用多個
KmlLayer
,而不要使用具備不同查詢參數的單一KmlLayer
。 - 使用壓縮的 KMZ 檔案縮減檔案大小。
- 如果您使用 Google Cloud Storage 或其他雲端儲存空間解決方案,請「避免」使用經簽署的網址或臨時權杖等功能來強制執行存取權控管。這類操作可能會意外造成快取作業無法執行。
- 將所有點的精確度降低為適當的精確度。
- 合併並簡化類似地圖項目 (例如多邊形和折線) 的幾何圖形。
- 移除所有未使用的元素或圖片資源。
- 移除所有不支援的元素。
如果您需要存取私人資料、防止快取,或是將瀏覽器可視區域傳送至地理空間資料伺服器做為查詢參數,建議您使用資料層,而非 KmlLayer
。這會引導使用者的瀏覽器直接向您的網路伺服器要求資源。
支援的 KML 元素
Maps JavaScript API 支援下列 KML 元素。KML 剖析器通常會自動忽略無法辨識的 XML 標記。
- 地標
- 圖示
- 資料夾
- 描述性 HTML:透過 <BalloonStyle> 和 <text> 的實體替代項目
- KMZ (壓縮過的 KML,包括附加圖片)
- 折線和多邊形
- 折線和多邊形樣式,包括顏色、填滿和不透明度
- 可動態匯入資料的網路連結
- 區域疊加層和螢幕疊加層
下表提供支援的 KML 元素完整詳細資料。
KML 元素 | API 是否支援? | 註解 |
---|---|---|
<address> | 否 | |
<AddressDetails> | 否 | |
<Alias> | 不適用 | 不支援 <Model> |
<altitude> | 否 | |
<altitudeMode> | 否 | |
<atom:author> | 是 | |
<atom:link> | 是 | |
<atom:name> | 是 | |
<BalloonStyle> | 部分支援 | 僅支援 <text> |
<begin> | 不適用 | 不支援 <TimeSpan> |
<bgColor> | 否 | |
<bottomFov> | 不適用 | 不支援 <PhotoOverlay> |
<Camera> | 否 | |
<Change> | 部分支援 | 僅支援樣式變更 |
<color> | 部分支援 | 包含 #AABBGGRR 和 #BBGGRR;<IconStyle>、<ScreenOverlay> 和 <GroundOverlay> 不支援 |
<colorMode> | 否 | |
<cookie> | 否 | |
<coordinates> | 是 | |
<Create> | 否 | |
<Data> | 是 | |
<Delete> | 否 | |
<description> | 是 | 允許 HTML 內容,但會經過清除,以免受到跨瀏覽器攻擊。不支援 $[dataName] 表單的實體替代項目。 |
<displayMode> | 否 | |
<displayName> | 否 | |
<Document> | 部分支援 | 默示支援子項;做為其他地圖項目的子項無效 |
<drawOrder> | 否 | |
<east> | 是 | |
<end> | 不適用 | 不支援 <TimeSpan> |
<expires> | 是 | 詳情請參閱「摘要」部分 |
<ExtendedData> | 部分支援 | 僅支援未經類型宣告的 <Data>,不支援 <SimpleData> 或 <Schema>,也不支援 $[dataName] 表單的實體替代項目。 |
<extrude> | 否 | |
<fill> | 是 | |
<flyToView> | 否 | |
<Folder> | 是 | |
<geomColor> | 否 | 已淘汰 |
<GeometryCollection> | 否 | 已淘汰 |
<geomScale> | 否 | 已淘汰 |
<gridOrigin> | 不適用 | 不支援 <PhotoOverlay> |
<GroundOverlay> | 是 | 無法旋轉 |
<h> | 是 | 已淘汰 |
<heading> | 是 | |
hint | 是 | 支援 target=... |
<hotSpot> | 是 | |
<href> | 是 | |
<httpQuery> | 否 | |
<Icon> | 是 | 無法旋轉 |
<IconStyle> | 是 | |
<ImagePyramid> | 不適用 | 不支援 <PhotoOverlay> |
<innerBoundaryIs> | 是 | 依 <LinearRing> 順序默示 |
<ItemIcon> | 不適用 | 不支援 <ListStyle> |
<key> | 不適用 | 不支援 <StyleMap> |
<kml> | 是 | |
<labelColor> | 否 | 已淘汰 |
<LabelStyle> | 否 | |
<latitude> | 是 | |
<LatLonAltBox> | 是 | |
<LatLonBox> | 是 | |
<leftFov> | 不適用 | 不支援 <PhotoOverlay> |
<LinearRing> | 是 | |
<LineString> | 是 | |
<LineStyle> | 是 | |
<Link> | 是 | |
<linkDescription> | 否 | |
<linkName> | 否 | |
<linkSnippet> | 否 | |
<listItemType> | 不適用 | 不支援 <ListStyle> |
<ListStyle> | 否 | |
<Location> | 不適用 | 不支援 <Model> |
<Lod> | 是 | |
<longitude> | 是 | |
<LookAt> | 否 | |
<maxAltitude> | 是 | |
<maxFadeExtent> | 是 | |
<maxHeight> | 不適用 | 不支援 <PhotoOverlay> |
<maxLodPixels> | 是 | |
<maxSessionLength> | 否 | |
<maxWidth> | 不適用 | 不支援 <PhotoOverlay> |
<message> | 否 | |
<Metadata> | 否 | 已淘汰 |
<minAltitude> | 是 | |
<minFadeExtent> | 是 | |
<minLodPixels> | 是 | |
<minRefreshPeriod> | 否 | <NetworkLink> |
<Model> | 否 | |
<MultiGeometry> | 部分支援 | 已進行算繪,但在左側面板中顯示為獨立地圖項目 |
<name> | 是 | |
<near> | 不適用 | 不支援 <PhotoOverlay> |
<NetworkLink> | 是 | |
<NetworkLinkControl> | 部分支援 | 部分支援 <Update> 和 <expires>。API 會忽略 HTTP 標頭中的到期時間設定,但會使用 KML 中指定的到期時間設定。如果沒有到期時間設定或在有效期間的間隔內,Google 地圖可能會快取從網際網路擷取的資料 (未指定持續時間)。重新命名文件並以不同網址擷取,或是確保文件包含適當的到期時間設定,都可以強制從網際網路重新擷取資料。 |
<north> | 是 | |
<open> | 是 | |
<Orientation> | 不適用 | 不支援 <Model> |
<outerBoundaryIs> | 是 | 依 <LinearRing> 順序默示 |
<outline> | 是 | |
<overlayXY> | 否 | |
<Pair> | 不適用 | 不支援 <StyleMap> |
<phoneNumber> | 否 | |
<PhotoOverlay> | 否 | |
<Placemark> | 是 | |
<Point> | 是 | |
<Polygon> | 是 | |
<PolyStyle> | 是 | |
<range> | 是 | |
<refreshInterval> | 部分支援 | 僅限 <Link>;<Icon> 不支援 |
<refreshMode> | 是 | 「onExpire」模式不支援 HTTP 標頭。請參閱上方的 <Update> 和 <expires> 註解。 |
<refreshVisibility> | 否 | |
<Region> | 是 | |
<ResourceMap> | 不適用 | 不支援 <Model> |
<rightFov> | 不適用 | 不支援 <PhotoOverlay> |
<roll> | 不適用 | 不支援 <Camera> 和 <Model> |
<rotation> | 否 | |
<rotationXY> | 否 | |
<Scale> | 不適用 | 不支援 <Model> |
<scale> | 否 | |
<Schema> | 否 | |
<SchemaData> | 否 | |
<ScreenOverlay> | 是 | 無法旋轉 |
<screenXY> | 否 | |
<shape> | 不適用 | 不支援 <PhotoOverlay> |
<SimpleData> | 不適用 | 不支援 <SchemaData> |
<SimpleField> | 不適用 | 不支援 <Schema> |
<size> | 是 | |
<Snippet> | 是 | |
<south> | 是 | |
<state> | 不適用 | 不支援 <ListStyle> |
<Style> | 是 | |
<StyleMap> | 否 | 不支援滑鼠游標懸停 (醒目顯示) 效果 |
<styleUrl> | 不適用 | 不支援 <StyleMap> |
<targetHref> | 部分支援 | <Update> 支援,<Alias> 不支援 |
<tessellate> | 否 | |
<text> | 是 | 不支援 $[geDirections] 替代項目 |
<textColor> | 否 | |
<tileSize> | 不適用 | 不支援 <PhotoOverlay> |
<tilt> | 否 | |
<TimeSpan> | 否 | |
<TimeStamp> | 否 | |
<topFov> | 不適用 | 不支援 <PhotoOverlay> |
<Update> | 部分支援 | 僅樣式變更,不支援 <Create> 或 <Delete> |
<Url> | 是 | 已淘汰 |
<value> | 是 | |
<viewBoundScale> | 否 | |
<viewFormat> | 否 | |
<viewRefreshMode> | 部分支援 | 支援「onStop」 |
<viewRefreshTime> | 是 | |
<ViewVolume> | 不適用 | 不支援 <PhotoOverlay> |
<visibility> | 部分支援 | 在 <Folder> 上支援 - 子項地標會沿用其中的瀏覽權限 |
<w> | 是 | 已淘汰 |
<west> | 是 | |
<when> | 不適用 | 不支援 <TimeStamp> |
<width> | 是 | |
<x> | 是 | 已淘汰 |
<y> | 是 | 已淘汰 |