Maps JavaScript API 2 版已於 2021 年 5 月 26 日停止提供。因此,您網站的 2 版地圖會停止運作,並傳回 JavaScript 錯誤。如要繼續在您的網站上使用地圖,請遷移至 Maps JavaScript API 3 版。本指南將協助您完成整個程序。
總覽
每個應用程式的遷移程序都會略有不同,但有些步驟適用於所有專案:
- 取得新的金鑰。Maps JavaScript API 現在使用 Google Cloud 控制台管理金鑰。如果您仍在使用第 2 版金鑰,請務必先取得新的 API 金鑰,再開始遷移作業。
- 更新 API 啟動程序。大多數應用程式會使用以下程式碼載入 Maps JavaScript API 3 版:
<script src="//maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
- 更新程式碼。所需的變更量很大程度上取決於您的應用程式。常見的變更包括:
- 請一律參照 google.maps 命名空間。在 v3 中,所有 Maps JavaScript API 程式碼都會儲存在
google.maps.*
命名空間中,而非全域命名空間。在這個程序中,我們也重新命名了大部分的物件。例如,您現在會載入 google.maps.Map
,而非 GMap2
。
- 移除所有已淘汰方法的參照。已移除許多通用的實用工具方法,例如
GDownloadURL
和 GLog
。請將這項功能替換為第三方公用程式庫,或從程式碼中移除這些參照。
- (選用) 在程式碼中加入程式庫。許多功能已外部化至公用程式庫,因此每個應用程式只需載入要使用的 API 部分。
- (選用) 設定專案以使用 v3 外部模組。
您可以使用 v3 外部函式,透過 Closure 編譯器驗證程式碼,或在 IDE 中觸發自動完成功能。進一步瞭解
進階編譯和外部變數。
- 測試並重複執行。此時您仍需完成一些工作,但好消息是,您將順利完成新版地圖應用程式 v3 的申請!
Maps JavaScript API 第 3 版的變更
在規劃遷移作業前,請先花時間瞭解 Maps JavaScript API 第 2 版和 Maps JavaScript API 第 3 版的差異。最新版本的 Maps JavaScript API 是從頭開始編寫,著重於新型 JavaScript 程式設計技巧、增加程式庫使用量,以及簡化 API。API 新增了許多新功能,並且有幾項熟悉的功能已變更或移除。本節重點說明這兩個版本之間的一些主要差異。
第 3 版 API 中的部分變更包括:
- 簡化的核心程式庫。許多輔助函式已移至程式庫,有助於縮短 Core API 的載入和剖析時間,讓地圖在任何裝置上都能快速載入。
- 改善多項功能的效能,例如多邊形算繪和標記放置。
- 用戶端用量限制的新做法,可更妥善地因應行動裝置 Proxy 和公司防火牆使用的共用位址。
- 新增對多款新式瀏覽器和行動瀏覽器的支援。已移除對 Internet Explorer 6 的支援。
- 移除了許多通用輔助類別 (
GLog
或
GDownloadUrl
)。目前有許多優異的 JavaScript 程式庫可提供類似功能,例如 Closure 或 jQuery。
- 街景服務導入了 HTML5 技術,因此在任何行動裝置上都能載入這項服務。
- 使用自己的相片製作自訂街景服務全景,方便您分享滑雪坡、待售房屋或其他有趣地點的全景。
- 樣式化地圖自訂功能,可讓您變更基本地圖上的元素顯示方式,以符合您獨特的視覺樣式。
- 支援多項新服務,例如 ElevationService 和 Distance Matrix。
- 改良版的路線指引服務提供替代路線、路線最佳化 (
旅行推銷員問題的近似解決方案)、單車路線 (含
單車路線圖層)、大眾運輸路線和
可拖曳路線。
- 更新版 Geocoding 格式,可提供比 Geocoding API 2 版
accuracy
值更準確的類型資訊。
- 支援在單一地圖上顯示多個資訊視窗
新的金鑰
Maps JavaScript API 第 3 版採用第 2 版的全新金鑰系統。您可能已經在應用程式中使用 v3 金鑰,在這種情況下,您不需要進行任何變更。如要確認,請檢查您用來載入 Maps JavaScript API 的網址是否含有 key
參數。如果鍵值開頭為「ABQIAA」,表示您使用的是 v2 鍵。如果您有 v2 金鑰,則必須在遷移期間升級至 v3 金鑰,這樣才能:
- 允許您在 Google Cloud Console 中監控 API 用量。
- 允許您在需要時購買額外配額。
- 方便 Google 就您的應用程式相關問題與您聯絡。
載入 Maps JavaScript API 第 3 版時,系統會傳遞這組金鑰。進一步瞭解如何產生 API 金鑰。
請注意,如果您是 Google Maps API for Work 客戶,可能會使用用戶端 ID 搭配 client
參數,而不是使用 key
參數。Maps JavaScript API v3 仍支援用戶端 ID,且不需要進行金鑰升級程序。
載入 API
您需要對程式碼進行的第一個修改,是涉及如何載入 API。在第 2 版中,您可以透過對 http://maps.google.com/maps
提出要求來載入 Maps JavaScript API。如果您要載入 Maps JavaScript API 第 3 版,則需要進行下列變更:
- 從
//maps.googleapis.com/maps/api/js
載入 API
- 移除
file
參數。
- 使用新的 v3 金鑰更新
key
參數。Google Maps API for Work 客戶應使用 client
參數。
- (僅限 Google 地圖平台付費方案) 請務必按照《
Google 地圖平台付費方案開發人員指南》所述,提供
client
參數。
- 移除
v
參數,以便要求最新發布的版本,或根據 v3 版本編號方案變更其值。
- (選用) 將
hl
參數替換為 language
,並保留其值。
- (選用) 新增
libraries
參數,以載入選用資料庫。
在最單純的情況下,第 3 版的 Bootstrap 只會指定 API 金鑰參數:
<script src="//maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
以下範例會以德文要求最新版的 Maps JavaScript API 第 2 版:
<script src="//maps.google.com/maps?file=api&v=2.x&key=YOUR_API_KEY&hl=de"></script>
下方範例針對第 3 版提出相同要求。
<script src="//maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&language=de"></script>
導入 google.maps 命名空間
Maps JavaScript API 第 3 版最明顯的變更,可能是引入 google.maps
命名空間。根據預設,v2 API 會將所有物件放入 Global 命名空間,這可能會導致命名衝突。在 v3 中,所有物件都位於 google.maps
命名空間中。
將應用程式遷移至 v3 時,您必須變更程式碼,才能使用新的命名空間。很抱歉,搜尋「G」並替換為「google.maps」並不會完全有效,但這是檢查程式碼時的好方法。以下列舉幾個 v2 和 v3 中等同的類別。
v2 |
v3 |
GMap2 |
google.maps.Map |
GLatLng |
google.maps.LatLng |
GInfoWindow |
google.maps.InfoWindow |
GMapOptions |
google.map.MapOptions |
G_API_VERSION |
google.maps.version |
GPolyStyleOptions |
google.maps.PolygonOptions or
google.maps.PolylineOptions |
移除過時的程式碼
Maps JavaScript API 3 版與 2 版的大部分功能相似,但有些類別已不再支援。在遷移作業中,您應將這些類別替換為第三方公用程式庫,或從程式碼中移除這些參照。許多優異的 JavaScript 程式庫都提供類似的功能,例如 Closure 或 jQuery。
下列類別在 Maps JavaScript API 第 3 版中沒有對應項目:
GBounds | GLanguage |
GBrowserIsCompatible | GLayer |
GControl | GLog |
GControlAnchor | GMercatorProjection |
GControlImpl | GNavLabelControl |
GControlPosition | GObliqueMercator |
GCopyright | GOverlay |
GCopyrightCollection | GPhotoSpec |
GDownloadUrl | GPolyEditingOptions |
GDraggableObject | GScreenOverlay |
GDraggableObjectOptions | GStreetviewFeatures |
GFactualGeocodeCache | GStreetviewLocation |
GGeoAddressAccuracy | GStreetviewOverlay |
GGeocodeCache | GStreetviewUserPhotosOptions |
GGoogleBar | GTileLayerOptions |
GGoogleBarAdsOptions | GTileLayerOverlayOptions |
GGoogleBarLinkTarget | GTrafficOverlayOptions |
GGoogleBarListingTypes | GUnload |
GGoogleBarOptions | GXml |
GGoogleBarResultList | GXmlHttp |
GInfoWindowTab | GXslt |
GKeyboardHandler |
|
比較程式碼
我們來比較兩個使用 v2 和 v3 API 編寫的簡單應用程式。
<!DOCTYPE html>
<html>
<head>
<script src="//maps.google.com/maps?file=api&v=2&key=YOUR_API_KEY"></script>
<style>
html, body, #map { height: 100%; margin: 0; }
</style>
<script>
function initialize() {
if (GBrowserIsCompatible()) {
var map = new GMap2(
document.getElementById('map'));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
map.setUIToDefault();
map.addOverlay(new GMarker(new GLatLng(37.4419, -122.1419)));
}
}
</script>
</head>
<body onload="initialize()" onunload="GUnload()">
<div id="map"></div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<script src="//maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
<style>
html, body, #map { height: 100%; margin: 0; }
</style>
<script>
function initialize() {
var map = new google.maps.Map(
document.getElementById('map'), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var marker = new google.maps.Marker({
position: new google.maps.LatLng(37.4419, -122.1419),
map: map
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>
如您所見,這兩個應用程式之間有幾個差異。明顯的改變包括:
- 載入 API 的位址已變更。
- 在 v3 中,系統不再需要
GBrowserIsCompatible()
和 GUnload()
方法,且已從 API 中移除。
GMap2
物件已由 google.maps.Map
取代,成為 API 中的核心物件。
- 屬性現在是透過 Options 類別載入。在上述範例中,我們透過內嵌的
MapOptions
物件,設定載入地圖所需的三個屬性:center
、zoom
和 mapTypeId
。
- 根據預設,第 3 版會啟用預設使用者介面。您可以在
MapOptions
物件中將 disableDefaultUI
屬性設為 true,即可停用此功能。
摘要
到目前為止,您應該已瞭解從 Maps JavaScript API 第 2 版遷移至第 3 版時,需要注意的部分重點。您可能需要瞭解更多資訊,但這取決於您的應用程式。在以下各節中,我們針對您可能遇到的特定情況,提供遷移操作說明。此外,升級過程中還有幾項實用資源。
如果您對本文有任何問題或疑問,請使用頁面頂端的「傳送意見回饋」連結。
本節將詳細比較 Maps JavaScript API 第 2 版和第 3 版最受歡迎的功能。參考資料的每個部分皆可單獨閱讀。我們建議您不要完整閱讀這份參考資料,而是視情況使用這項資料來協助遷移。
- 事件 - 註冊及處理事件。
- 控制項:操控地圖上顯示的導覽控制項。
- 疊加層:在地圖上新增及編輯物件。
- 地圖類型:組成基本地圖的圖塊。
- 圖層:以群組為單位新增及編輯內容,例如 KML 或交通圖層。
- 服務:使用 Google 地理編碼、路線或街景服務。
活動
Maps JavaScript API 第 3 版的事件模型與第 2 版的類似,但實際上有許多變更。
支援 MVC 的新事件
第 3 版 API 添加了一個新的事件類型,以反映 MVC 狀態變更。目前有兩種類型的事件:
- 使用者事件 (例如「點擊」滑鼠事件) 會從 DOM 傳播至 Maps JavaScript API。這些事件與標準 DOM 事件各自獨立,也互不相同。
- MVC 狀態變更通知會反映 Maps API 物件的變更,並採用
property_changed
慣例命名。
每個 Maps API 物件匯出一系列具名的事件。與特定事件相關的應用程式應為這些事件註冊事件監聽器,並在收到事件時執行程式碼。這個事件驅動機制在 Maps JavaScript API 第 2 版和第 3 版中都相同,唯一的差別是命名空間從 GEvent
變更為 google.maps.event
:
GEvent.addListener(map, 'click', function() {
alert('You clicked the map.');
});
google.maps.event.addListener(map, 'click', function() {
alert('You clicked the map.');
});
移除事件監聽器
基於效能考量,建議您在不再需要事件監聽器時予以移除。在 v2 和 v3 中,移除事件監聽器的運作方式相同:
- 建立事件監聽器時,系統會傳回不透明物件 (v2 中的 GEventListener、v3 中的 MapsEventListener)。
- 如要移除事件監聽器,請將這個物件傳遞至
removeListener()
方法 (v2 中的 GEvent.removeListener()
或 v3 中的 google.maps.event.removeListener()
),以移除事件監聽器。
監聽 DOM 事件
如要擷取及回應 DOM (文件物件模型) 事件,v3 提供 google.maps.event.addDomListener()
靜態方法,相當於 v2 中的 GEvent.addDomListener()
方法。
在事件中使用傳遞的引數
使用者介面事件通常會傳遞事件引數,事件監聽器可隨後存取該引數。為使 API 中的物件更一致,我們已簡化 v3 中大部分的事件引數。(詳情請參閱 v3 參考資料)。
v3 事件監聽器中沒有 overlay
引數。如果您在 v3 地圖上註冊 click
事件,回呼只會在使用者點選底圖時發生。如果您需要對這些點擊做出回應,可以為可點選的疊加層註冊其他回呼。
// Passes an overlay argument when clicking on a map
var map = new GMap2(document.getElementById('map'));
map.setCenter(new GLatLng(-25.363882, 131.044922), 4);
map.setUIToDefault();
GEvent.addListener(map,'click', function(overlay, latlng) {
if (latlng) {
var marker = new GMarker(latlng);
map.addOverlay(marker);
}
});
// Passes only an event argument
var myOptions = {
center: new google.maps.LatLng(-25.363882, 131.044922),
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map'),
myOptions);
google.maps.event.addListener(map, 'click', function(event) {
var marker = new google.maps.Marker({
position: event.latLng,
map: map
});
});
控制項
Maps JavaScript API 會顯示 UI 控制項,讓使用者與地圖互動。您可以使用 API 自訂這些控制項的顯示方式。
控制項類型的變更
我們已在 v3 API 中引入 control
類型的部分變更。
- v3 API 支援其他地圖類型,包括地形地圖和新增自訂地圖類型的功能。
- v2 階層控制項
GHierarchicalMapTypeControl
已無法使用。您可以使用 google.maps.MapTypeControlStyle.HORIZONTAL_BAR
控制項達到類似效果。
- 在第 3 版中,第 2 版中
GMapTypeControl
提供的水平版面配置無法使用。
在地圖中加入控制項
使用 Maps JavaScript API 第 2 版時,您可以透過地圖物件的 addControl()
方法,在地圖中加入控制項。在 v3 中,您可以修改相關聯的 MapOptions
物件,而非直接存取或修改控制項。以下範例說明如何自訂地圖,以便新增下列控制項:
var map = new GMap2(document.getElementById('map'));
map.setCenter(new GLatLng(-25.363882, 131.044922), 4);
// Add controls
map.addControl(new GMapTypeControl());
map.addControl(new GScaleControl());
var myOptions = {
center: new google.maps.LatLng(-25.363882, 131.044922),
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP,
// Add controls
mapTypeControl: true,
scaleControl: true
};
var map = new google.maps.Map(document.getElementById('map'),
myOptions);
在地圖上放置控制項
放置控制項功能在第 3 版中有大幅變更。在 v2 中,addControl()
方法會採用選用的第二個參數,讓您指定控制項相對於地圖角落的位置。
在 v3 中,您可以透過控制項選項的 position
屬性設定控制項的位置。這些控制項並沒有固定位置,但 API 會在指定限制範圍內 (例如地圖尺寸) 巧妙地配置這些控制項,分布在現有地圖元素周圍。這樣可確保預設控制項與您的控制項相容。詳情請參閱「在 v3 中控制廣告位置」。
下列程式碼重新設定上述範例的控制項位置:
var map = new GMap2(document.getElementById('map'));
map.setCenter(new GLatLng(-25.363882, 131.044922), 4);
// Add map type control
map.addControl(new GMapTypeControl(), new GControlPosition(
G_ANCHOR_TOP_LEFT, new GSize(10, 10)));
// Add scale
map.addControl(new GScaleControl(), new GControlPosition(
G_ANCHOR_BOTTOM_RIGHT, new GSize(20, 20)));
var myOptions = {
center: new google.maps.LatLng(-25.363882, 131.044922),
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP,
// Add map type control
mapTypeControl: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
position: google.maps.ControlPosition.TOP_LEFT
},
// Add scale
scaleControl: true,
scaleControlOptions: {
position: google.maps.ControlPosition.BOTTOM_RIGHT
}
};
var map = new google.maps.Map(document.getElementById('map'),
myOptions);
自訂控制項
您可以使用 Maps JavaScript API 建立自訂導覽控制項。如要使用 v2 API 自訂控制項,您必須將 GControl
類別設為子類別,並為 initialize()
和 getDefaultPosition()
方法定義處理程序。在 v3 中,沒有 GControl
類別的對應項目。而是以 DOM 元素表示控制項。如要使用 v3 API 新增自訂控制項,請在建構函式中為控制項建立 DOM 結構,做為 Node
(例如 <div>
元素) 的子項,並新增事件監聽器來處理任何 DOM 事件。將 Node
推送至地圖的 controls[position]
陣列,即可將自訂控制項的例項新增至地圖。
假設 HomeControl
類別實作方式符合上述介面需求 (詳情請參閱「自訂控制項」說明文件),以下程式碼範例說明如何將自訂控制項加進地圖。
map.addControl(new HomeControl(),
GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(10, 10)));
var homeControlDiv = document.createElement('DIV');
var homeControl = new HomeControl(homeControlDiv, map);
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(
homeControlDiv);
重疊說明
疊加層會反映您「新增」至地圖的物件,用於指定點、線、面或物件集合。
新增與移除疊加層
Overlay 所代表的物件類型在 v2 和 v3 之間相同,但處理方式不同。
使用 GMap2
物件的 addOverlay()
和 removeOverlay()
方法,在 v2 API 中新增及移除疊加層。在 v3 中,您可以透過相關疊加層選項類別的 map
屬性,將地圖指派給疊加層。您也可以直接呼叫疊加層物件的 setMap()
方法,並指定所需地圖,藉此新增或移除疊加層。將地圖屬性設為 null
即可移除疊加層。
在 v3 中不存在 clearOverlays()
方法。如要管理一組疊加層,請建立陣列來存放疊加層。您可以使用這個陣列,針對陣列中的每個覆疊呼叫 setMap()
(如果需要移除覆疊,請傳遞 null
)。
可拖曳的標記
根據預設,標記可供點擊但不可拖曳。以下兩個範例會新增可拖曳的標記:
var myLatLng = new GLatLng(-25.363882, 131.044922);
var map = new GMap2(document.getElementById('map'));
map.setCenter(myLatLng, 4);
var marker = new GMarker(latLng, {
draggable: true
});
map.addOverlay(marker);
var myLatLng = new google.maps.LatLng(-25.363882, 131.044922);
var map = new google.maps.Map(
document.getElementById('map'), {
center: myLatLng,
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var marker = new google.maps.Marker({
position: myLatLng,
draggable: true,
map: map
});
圖示
您可以定義自訂圖示,以取代預設標記。如要在 v2 中使用自訂映像檔,您可以從 G_DEFAULT_ICON type
建立 GIcon
例項,然後加以修改。如果圖片大於或小於預設圖示,您必須使用 GSize
例項指定圖示。v3 API 稍微簡化了這個程序。只要將標記的 icon
屬性設為自訂圖片的網址,API 就會自動調整圖示大小。
Maps JavaScript API 也支援複雜的圖示。複雜圖示可能包含多個圖塊、複雜形狀,或指定圖片相對於其他疊加層的顯示方式 (即「堆疊順序」)。如要在 v2 中為標記新增形狀,您需要在每個 GIcon
例項中指定額外屬性,並將其做為選項傳遞至 GMarker
建構函式。在 v3 中,透過這種方式指定的圖示應將其 icon
屬性設為 Icon
類型的物件。版本 3 不支援標記陰影。
以下範例顯示澳洲 Bondi Beach 的海灘旗幟,圖示的透明部分無法點選:
var map = new GMap2(document.getElementById('map'));
map.setCenter(new GLatLng(-25.363882, 131.044922), 4);
map.setUIToDefault();
var flagIcon = new GIcon(G_DEFAULT_ICON);
flagIcon.image = '/images/beachflag.png';
flagIcon.imageMap = [1, 1, 1, 20, 18, 20, 18 , 1];
var bbLatLng = new GLatLng(-33.890542, 151.274856);
map.addOverlay(new GMarker(bbLatLng, {
icon: flagIcon
}));
var map = new google.maps.Map(
document.getElementById('map'), {
center: new google.maps.LatLng(-25.363882, 131.044922),
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var shape = {
coord: [1, 1, 1, 20, 18, 20, 18 , 1],
type: 'poly'
};
var bbLatLng = new google.maps.LatLng(-33.890542, 151.274856);
var bbMarker = new google.maps.Marker({
icon: '/images/beachflag.png'
shape: shape,
position: bbLatLng,
map: map
});
折線
折線由 LatLng
陣列組成,加上一系列線段,依序連接這些位置。在 v3 中建立及顯示 Polyline
物件,與在 v2 中使用 GPolyline
物件類似。下列範例會繪製半透明的 3 像素寬測地線折線,從蘇黎世經由新加坡前往雪梨:
var polyline = new GPolyline(
[
new GLatLng(47.3690239, 8.5380326),
new GLatLng(1.352083, 103.819836),
new GLatLng(-33.867139, 151.207114)
],
'#FF0000', 3, 0.5, {
geodesic: true
});
map.addOverlay(polyline);
var polyline = new google.maps.Polyline({
path: [
new google.maps.LatLng(47.3690239, 8.5380326),
new google.maps.LatLng(1.352083, 103.819836),
new google.maps.LatLng(-33.867139, 151.207114)
],
strokeColor: '#FF0000',
strokeOpacity: 0.5,
strokeWeight: 3,
geodesic: true
});
polyline.setMap(map);
地理編碼折線
v3 不支援直接從已編碼的多邊形建立 Polyline
物件。相反地,幾何圖形程式庫提供編碼及解碼折線的方法。如要進一步瞭解如何載入這個程式庫,請參閱 v3 Maps API 中的「程式庫」。
以下範例會繪製相同的已編碼多邊形;v3 程式碼會使用 google.maps.geometry.encoding
命名空間中的 decodePath()
方法。
var polyline = new GPolyline.fromEncoded({
points: 'kwb`Huqbs@ztzwGgvpdQbw}uEoif`H',
levels: 'PPP',
zoomFactor: 2,
numLevels: 18,
color: '#ff0000',
opacity: 0.8,
weight: 3
});
map.addOverlay(polyline);
var polyline = new google.maps.Polyline({
path: google.maps.geometry.encoding.decodePath(
'kwb`Huqbs@ztzwGgvpdQbw}uEoif`H'),
strokeColor: '#FF0000',
strokeOpacity: 0.5,
strokeWeight: 3,
});
polyline.setMap(map);
多邊形
「多邊形」指的是頭尾相連的多角線段所構成的封閉型區塊。Polygon
物件與 Polyline
物件非常相似,都是由一系列點依序組成。v3 Polygon
類別與 v2 GPolygon
類別大致相同,但值得注意的是,您不再需要在路徑結尾重複起始頂點,即可關閉迴圈。v3 API 會繪製一段線條,將最後一個座標接回第一個座標,自動關閉任何多邊形。以下程式碼片段會建立代表百慕達三角洲的多邊形:
var map = new GMap2(document.getElementById('map'));
map.setCenter(new GLatLng(24.886436, -70.268554), 5);
var bermudaTriangle = new GPolygon(
[
new GLatLng(25.774252, -80.190262),
new GLatLng(18.466465, -66.118292),
new GLatLng(32.321384, -64.75737),
new GLatLng(25.774252, -80.190262)
],
'#FF0000', 2, 0.8, '#FF0000', 0.35);
map.addOverlay(bermudaTriangle);
var map = new google.maps.Map(document.getElementById('map'), {
center: new google.maps.LatLng(24.886436, -70.268554),
mapTypeId: google.maps.MapTypeId.TERRAIN,
zoom: 5
});
var bermudaTriangle = new google.maps.Polygon({
paths: [
new google.maps.LatLng(25.774252, -80.190262),
new google.maps.LatLng(18.466465, -66.118292),
new google.maps.LatLng(32.321384, -64.75737)
],
strokeColor: '#FF0000',
strokeWeight: 2,
strokeOpacity: 0.8,
fillColor: '#FF0000',
fillOpacity: 0.35
});
bermudaTriangle.setMap(map);
使用者可編輯的形狀
您可將折線和多邊形設為允許使用者編輯。以下程式碼片段的作用相同:
map.addOverlay(polyline);
polyline.enableEditing();
polyline.setMap(map);
polyline.setEditable(true);
如需更進階的繪圖功能,請參閱第 3 版說明文件中的「繪圖程式庫」。
資訊視窗
InfoWindow
會在地圖上方浮動式視窗中顯示內容。v2 和 v3 資訊視窗之間有幾個主要差異:
- v2 API 僅支援每個地圖一個
GInfoWindow
,而 v3 API 則支援每個地圖多個並行的 InfoWindow
。
- 點選地圖時,v3
InfoWindow
會保持開啟狀態。點選地圖時,v2 GInfoWindow
會自動關閉。您可以在 Map
物件上新增 click
事件監聽器,模擬 v2 行為。
- v3 API 不提供分頁
InfoWindow
的原生支援。
區域疊加層
如要將圖片加進地圖,請使用 GroundOverlay
物件。GroundOverlay
的建構函式在 v2 和 v3 中基本上相同:它會將圖片的網址和圖片邊界指定為參數。
以下範例將紐澤西州紐華克的古地圖置於地圖上做為疊加層:
var bounds = new GLatLngBounds(
new GLatLng(40.716216, -74.213393),
new GLatLng(40.765641, -74.139235));
var overlay = new GGroundOverlay(
'http://lib.utexas.edu/maps/historical/newark_nj_1922.jpg',
bounds);
map.addOverlay(overlay);
var bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(40.716216, -74.213393),
new google.maps.LatLng(40.765641, -74.139235));
var overlay = new google.maps.GroundOverlay(
'http://lib.utexas.edu/maps/historical/newark_nj_1922.jpg',
bounds);
overlay.setMap(map);
地圖類型
雖然 v2 和 v3 提供的地圖類型略有不同,但兩個 API 版本都提供所有基本地圖類型。根據預設,v2 會使用標準的「繪製」道路地圖圖塊。不過,v3 要求在建立 google.maps.Map
物件時,必須提供特定地圖類型。
常用地圖類型
第 2 版和第 3 版皆提供下列 4 種基本地圖類型:
MapTypeId.ROADMAP
(取代 G_NORMAL_MAP
) 會顯示道路地圖檢視畫面。
MapTypeId.SATELLITE
(取代 G_SATELLITE_MAP
) 會顯示 Google 地球衛星圖像。
MapTypeId.HYBRID
(取代 G_HYBRID_MAP
) 會顯示一般檢視和衛星檢視的混合畫面。
MapTypeId.TERRAIN
(取代 G_PHYSICAL_MAP
) 會根據地形資訊顯示實際地圖。
下方範例顯示在第 2 版和第 3 版中如何將地圖設定為地形檢視:
map.setMapType(G_PHYSICAL_MAP);
map.setMapTypeId(google.maps.MapTypeId.TERRAIN);
Maps JavaScript API 第 3 版也對較不常見的地圖類型進行了一些變更:
- 除了地球以外,天體的地圖圖塊無法做為 v3 API 中的地圖類型,但可做為自訂地圖類型存取,如此範例所示。
- v3 中沒有特殊地圖類型可取代 v2 中的
G_SATELLITE_3D_MAP
類型。您可以改用這個程式庫,在 v3 地圖中整合 Google 地球外掛程式。
最大縮放圖像
並非所有衛星圖像都具備高倍縮放能力。如果您想在設定縮放等級前瞭解可用的最高縮放等級,請使用 google.maps.MaxZoomService
類別。這個類別會取代 v2 中的 GMapType.getMaxZoomAtLatLng()
方法。
var point = new GLatLng(
180 * Math.random() - 90, 360 * Math.random() - 180);
var map = new GMap2(document.getElementById("map"));
map.setUIToDefault();
map.setCenter(point);
map.setMapType(G_HYBRID_MAP);
map.getCurrentMapType().getMaxZoomAtLatLng(point,
function(response) {
if (response.status) {
map.setZoom(response.zoom);
} else {
alert("Error in Max Zoom Service.");
}
});
var myLatlng = new google.maps.LatLng(
180 * Math.random() - 90, 360 * Math.random() - 180);
var map = new google.maps.Map(
document.getElementById("map"),{
zoom: 0,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.HYBRID
});
var maxZoomService = new google.maps.MaxZoomService();
maxZoomService.getMaxZoomAtLatLng(
myLatlng,
function(response) {
if (response.status == google.maps.MaxZoomStatus.OK) {
map.setZoom(response.zoom);
} else {
alert("Error in Max Zoom Service.");
}
});
空照透視圖像
在 v3 中啟用空拍影像時,控制項類似於 v2 的 GLargeZoomControl3D
控制項,並額外提供旋轉控制項,可旋轉至支援的方向。
您可以在這張地圖上追蹤目前提供 45° 圖像的城市。當 45° 圖像可用時,Maps API 衛星圖層按鈕會新增子選單選項。
圖層
「圖層」是指地圖上的物件,包含一或多個疊加層。可做為單一單位進行操作,通常會反映物件的集合。
支援的圖層
第 3 版 API 提供幾種不同圖層的使用。這些層會在下列區域與 v2 GLayer
類別重疊:
-
KmlLayer
物件會將 KML 和 GeoRSS 元素算繪成 v3 疊加層,提供與 v2 GeoXml
圖層等同的功能。
TrafficLayer
物件會算繪路況圖層,類似 v2 GTrafficOverlay
疊加層。
這些圖層與第 2 版的圖層不同,
請參閱下方說明。您可以呼叫 setMap()
,並傳遞要顯示圖層的 Map
物件,將圖層加入地圖。
如要進一步瞭解支援的圖層,請參閱圖層說明文件。
KML 與 GeoRSS 圖層
Maps JavaScript API 支援顯示地理資訊的 KML 和 GeoRSS 資料格式。如果您想在地圖中加入 KML 或 GeoRSS 檔案,這些檔案必須可供大眾存取。在 v3 中,這些資料格式會透過 KmlLayer
的例項顯示,取代 v2 中的 GGeoXml
物件。
在算繪 KML 時,v3 API 的彈性更高,可讓您抑制 InfoWindows 並修改點擊回應。詳情請參閱第 3 版的 KML 與 GeoRSS 圖層說明文件。
算繪 KmlLayer
時,會套用大小和複雜度限制;詳情請參閱 KmlLayer 說明文件。
下列範例比較 KML 檔案的載入方式。
geoXml = new GGeoXml(
'https://googlearchive.github.io/js-v2-samples/ggeoxml/cta.kml');
map.addOverlay(geoXml);
var layer = new google.maps.KmlLayer(
'https://googlearchive.github.io/js-v2-samples/ggeoxml/cta.kml', {
preserveViewport: true
});
layer.setMap(map);
路況圖層
您可以透過 v3 使用 TrafficLayer
物件,在地圖中加入即時路況資訊 (如有支援)。系統會根據要求的時間提供路況資訊。以下範例顯示洛杉磯的路況資訊:
var map = new GMap2(document.getElementById('map'));
map.setCenter(new GLatLng(34.0492459, -118.241043), 13);
map.setUIToDefault();
var trafficOptions = {incidents:false};
trafficInfo = new GTrafficOverlay(trafficOptions);
map.addOverlay(trafficInfo);
var map = new google.maps.Map(
document.getElementById('map'), {
center: new google.maps.LatLng(34.0492459, -118.241043),
mapTypeId: google.maps.MapTypeId.ROADMAP,
zoom: 13
});
var trafficLayer = new google.maps.TrafficLayer();
trafficLayer.setMap(map);
與 v2 不同,v3 中沒有 TrafficLayer
建構函式的選項。事件不適用於 v3。
服務
地理編碼
Maps JavaScript API 提供 geocoder
物件,可根據使用者輸入內容,動態地對地址進行地理編碼。如要針對已知靜態地址進行地理編碼,請參閱 Geocoding API 說明文件。
Geocoding API 已大幅升級和強化,新增功能並變更資料呈現方式。
v2 API 中的 GClientGeocoder
提供兩種不同的方法,用於正向和反向地理編碼,以及其他方法,用於影響地理編碼的執行方式。相反地,v3 Geocoder
物件只提供 geocode()
方法,該方法會採用含有輸入字詞的物件常值 (以 Geocoding Requests 物件形式) 和回呼方法。視要求是否包含文字 address
屬性或 LatLng
物件而定,Geocoding API 會傳回正向或反向地理編碼回應。您可以將其他欄位傳遞至地理編碼要求,藉此影響地理編碼的執行方式:
- 加入文字
address
會觸發正向地理編碼,等同於呼叫 getLatLng()
方法。
- 加入
latLng
物件會觸發反向地理編碼,相當於呼叫 getLocations()
方法。
- 加入
bounds
屬性可啟用Viewport 偏差,這等同於呼叫 setViewport()
方法。
- 加入
region
屬性可啟用區域代碼偏好設定,這等同於呼叫 setBaseCountryCode()
方法。
v3 中的地理編碼回應與 v2 回應截然不同。v3 API 會將 v2 使用的巢狀結構取代為更容易剖析的平面結構。此外,v3 回應更為詳細:每個結果都有幾個地址元件,可協助您進一步瞭解每個結果的解析度。
以下程式碼會擷取文字地址,並顯示地理編碼後的第一個結果:
var geocoder = new GClientGeocoder();
var infoPanel;
var map;
var AccuracyDescription = [
'Unknown accuracy', 'country level accuracy',
'region level accuracy', 'sub-region level accuracy',
'town level accuracy', 'post code level accuracy',
'street level accuracy', 'intersection level accuracy',
'address level accuracy', 'premise level accuracy',
];
function geocode_result_handler(response) {
if (!response || response.Status.code != 200) {
alert('Geocoding failed. ' + response.Status.code);
} else {
var bounds = new GLatLngBounds(new GLatLng(
response.Placemark[0].ExtendedData.LatLonBox.south,
response.Placemark[0].ExtendedData.LatLonBox.west
), new GLatLng(
response.Placemark[0].ExtendedData.LatLonBox.north,
response.Placemark[0].ExtendedData.LatLonBox.east
));
map.setCenter(bounds.getCenter(),
map.getBoundsZoomLevel(bounds));
var latlng = new GLatLng(
response.Placemark[0].Point.coordinates[1],
response.Placemark[0].Point.coordinates[0]);
infoPanel.innerHTML += '<p>1st result is <em>' +
// No info about location type
response.Placemark[0].address +
'</em> of <em>' +
AccuracyDescription[response.Placemark[0].
AddressDetails.Accuracy] +
'</em> at <tt>' + latlng + '</tt></p>';
var marker_title = response.Placemark[0].address +
' at ' + latlng;
map.clearOverlays();
var marker = marker = new GMarker(
latlng,
{'title': marker_title}
);
map.addOverlay(marker);
}
}
function geocode_address() {
var address = document.getElementById('input-text').value;
infoPanel.innerHTML = '<p>Original address: ' + address + '</p>';
geocoder.getLocations(address, geocode_result_handler);
}
function initialize() {
map = new GMap2(document.getElementById('map'));
map.setCenter(new GLatLng(38, 15), 2);
map.setUIToDefault();
infoPanel = document.getElementById('info-panel');
}
var geocoder = new google.maps.Geocoder();
var infoPanel;
var map;
var marker;
function geocode_result_handler(result, status) {
if (status != google.maps.GeocoderStatus.OK) {
alert('Geocoding failed. ' + status);
} else {
map.fitBounds(result[0].geometry.viewport);
infoPanel.innerHTML += '<p>1st result for geocoding is <em>' +
result[0].geometry.location_type.toLowerCase() +
'</em> to <em>' +
result[0].formatted_address + '</em> of types <em>' +
result[0].types.join('</em>, <em>').replace(/_/, ' ') +
'</em> at <tt>' + result[0].geometry.location +
'</tt></p>';
var marker_title = result[0].formatted_address +
' at ' + latlng;
if (marker) {
marker.setPosition(result[0].geometry.location);
marker.setTitle(marker_title);
} else {
marker = new google.maps.Marker({
position: result[0].geometry.location,
title: marker_title,
map: map
});
}
}
}
function geocode_address() {
var address = document.getElementById('input-text').value;
infoPanel.innerHTML = '<p>Original address: ' + address + '</p>';
geocoder.geocode({'address': address}, geocode_result_handler);
}
function initialize() {
map = new google.maps.Map(document.getElementById('map'), {
center: new google.maps.LatLng(38, 15),
zoom: 2,
mapTypeId: google.maps.MapTypeId.HYBRID
});
infoPanel = document.getElementById('info-panel');
}
路線
Maps JavaScript API 第 3 版會將第 2 版的 GDirections
類別替換為 DirectionsService
類別,用於計算路線。
v3 中的 route()
方法會取代 v2 API 中的 load()
和 loadFromWaypoints()
方法。這個方法會使用單一 DirectionsRequest
物件常值,其中包含輸入字詞和回呼方法,以便在收到回應時執行。您可以在這個物件常值中提供選項,類似於 v2 中的 GDirectionsOptions
物件常值。
在 Maps JavaScript API 第 3 版中,提交路線要求的工作已與轉譯要求的工作分開,後者現在則是透過 DirectionsRenderer
類別處理。您可以透過 setMap()
和 setDirections()
方法,將 DirectionsRenderer
物件繫結至任何地圖或 DirectionsResult
物件。由於轉譯器為 MVCObject
,因此可偵測其中屬性的任何變更,然後在相關聯的路線有異動時更新地圖。
以下程式碼示範如何使用地址中的行人路線,要求前往特定地點的步行路線。請注意,只有 v3 能夠在都柏林動物園的步行路線上提供步行路線。
var map;
var directions;
var directionsPanel;
function initialize() {
var origin = new google.maps.LatLng(53.348172, -6.297285);
var destination = new google.maps.LatLng(53.355502, -6.30557);
directionsPanel = document.getElementById("route");
map = new GMap2(document.getElementById('map'));
map.setCenter(origin, 10);
map.setUIToDefault();
directions = new GDirections(map, directionsPanel);
directions.loadFromWaypoints(
[origin, destination], {
travelMode: 'G_TRAVEL_MODE_WALKING',
});
}
var map;
var directionsRenderer;
var directionsService = new google.maps.DirectionsService();
function initialize() {
var origin = new google.maps.LatLng(53.348172, -6.297285);
var destination = new google.maps.LatLng(53.355502, -6.30557);
directionsRenderer = new google.maps.DirectionsRenderer();
map = new google.maps.Map(
document.getElementById('map'), {
center: origin,
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
directionsRenderer.setPanel(document.getElementById("route"));
directionsRenderer.setMap(map);
directionsService.route({
origin: origin,
destination: destination,
travelMode: google.maps.DirectionsTravelMode.WALKING
}, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsRenderer.setDirections(result);
}
});
}
街景服務
Google 街景服務可讓您在涵蓋區域內的指定地點進行 360 度互動式檢視。與需要使用 Flash® 外掛程式才能顯示街景服務圖像的 v2 不同,v3 API 可在瀏覽器中原生支援街景服務。
您可以使用 v3 中的 StreetViewPanorama
物件,或 v2 中的 GStreetviewPanorama
物件,支援街景服務圖片。這些類別具有不同的介面,但扮演相同的角色:將 div
容器連結至街景服務圖像,並讓您指定街景服務全景的所在位置和視角。
function initialize() {
var fenwayPark = new GLatLng(42.345573, -71.098326);
panoramaOptions = {
latlng: fenwayPark,
pov: {
heading: 35,
pitch: 5,
zoom: 1
}
};
var panorama = new GStreetviewPanorama(
document.getElementById('pano'),
panoramaOptions);
GEvent.addListener(myPano, "error", handleNoFlash);
}
function handleNoFlash(errorCode) {
if (errorCode == FLASH_UNAVAILABLE) {
alert('Error: Your browser does not support Flash');
return;
}
}
function initialize() {
var fenway = new google.maps.LatLng(42.345573, -71.098326);
var panoramaOptions = {
position: fenway,
pov: {
heading: 35,
pitch: 5,
zoom: 1
}
};
var panorama = new google.maps.StreetViewPanorama(
document.getElementById('pano'),
panoramaOptions);
}
您可以透過 v3 中的 StreetViewService
物件,或 v2 中的類似 GStreetviewClient
物件,直接存取街景服務資料。兩者都提供類似的介面,可用來擷取或檢查街景服務資料是否可用,並可依據位置或全景 ID 進行搜尋。
在第 3 版中,街景服務是預設啟用的服務。地圖會顯示街景服務衣夾人控制項,而 API 會重複使用地圖 div 來顯示街景服務全景。以下程式碼說明如何模擬 v2 行為,將街景服務全景分割成個別的 div。
var marker;
var panoClient = new GStreetviewClient();
function initialize() {
if (GBrowserIsCompatible()) {
var myPano = new GStreetviewPanorama(
document.getElementById('pano'));
GEvent.addListener(myPano, 'error', handleNoFlash);
var map = new GMap2(document.getElementById('map'));
map.setCenter(new GLatLng(42.345573, -71.098326), 16);
map.setUIToDefault();
GEvent.addListener(map, 'click', function(overlay, latlng) {
if (marker) {
marker.setLatLng(latlng);
} else {
marker = new GMarker(latlng);
map.addOverlay(marker);
}
var nearestPano = panoClient.getNearestPanorama(
latlng, processSVData);
});
function processSVData(panoData) {
if (panoData.code != 200) {
alert("Panorama data not found for this location.");
}
var latlng = marker.getLatLng();
var dLat = latlng.latRadians()
- panoData.location.latlng.latRadians();
var dLon = latlng.lngRadians()
- panoData.location.latlng.lngRadians();
var y = Math.sin(dLon) * Math.cos(latlng.latRadians());
var x = Math.cos(panoData.location.latlng.latRadians()) *
Math.sin(latlng.latRadians()) -
Math.sin(panoData.location.latlng.latRadians()) *
Math.cos(latlng.latRadians()) * Math.cos(dLon);
var bearing = Math.atan2(y, x) * 180 / Math.PI;
myPano.setLocationAndPOV(panoData.location.latlng, {
yaw: bearing
});
}
function handleNoFlash(errorCode) {
if (errorCode == FLASH_UNAVAILABLE) {
alert('Error: Your browser does not support Flash');
return;
}
}
}
}
// Load the API with libraries=geometry
var map;
var marker;
var panorama;
var sv = new google.maps.StreetViewService();
function radians(degrees) { return Math.PI * degrees / 180.0 };
function initialize() {
panorama = new google.maps.StreetViewPanorama(
document.getElementById("pano"));
map = new google.maps.Map(
document.getElementById('map'), {
center: new google.maps.LatLng(42.345573, -71.098326),
mapTypeId: google.maps.MapTypeId.ROADMAP,
zoom: 16
});
google.maps.event.addListener(map, 'click', function(event) {
if (!marker) {
marker = new google.maps.Marker({
position: event.latLng,
map: map
});
} else {
marker.setPosition(event.latLng);
}
sv.getPanoramaByLocation(event.latLng, 50, processSVData);
});
}
function processSVData(panoData, status) {
if (status == google.maps.StreetViewStatus.OK) {
alert("Panorama data not found for this location.");
}
var bearing = google.maps.geometry.spherical.computeHeading(
panoData.location.latLng, marker.getPosition());
panorama.setPano(panoData.location.pano);
panorama.setPov({
heading: bearing,
pitch: 0,
zoom: 1
});
panorama.setVisible(true);
marker.setMap(panorama);
}