Maps JavaScript API 2 版已於 2021 年 5 月 26 日停止提供。因此,您網站的 2 版地圖會停止運作,並傳回 JavaScript 錯誤。如要繼續在您的網站上使用地圖,請遷移至 Maps JavaScript API 3 版。本指南將引導您完成相關程序。
總覽
每個應用程式的遷移程序略有不同,但所有專案都應採取下列步驟:
- 取得新的金鑰。Maps JavaScript API 現在會使用 Google Cloud Console 管理金鑰。如果您仍在使用 v2 金鑰,請務必先取得新的 API 金鑰,再開始遷移。
- 更新 API 開機磁碟。大多數應用程式會使用以下程式碼載入 Maps JavaScript API 3 版:
<script src="//maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
- 更新程式碼。您需要進行的變更數量取決於應用程式。常見的變更包括:
- 一律參照 google.maps 命名空間。在第 3 版中,所有 Maps JavaScript API 程式碼都會儲存在
google.maps.*
命名空間,而非全域命名空間。在這項程序中,大部分物件也已重新命名。舉例來說,您現在可以載入 google.maps.Map
,而不是 GMap2
。
- 移除過時方法的任何參照。已移除許多一般用途的公用程式方法,例如
GDownloadURL
和 GLog
。請將這項功能替換為第三方公用程式庫,或是從程式碼中移除這些參照。
- (選用) 在程式碼中新增程式庫。許多功能已外部化為公用程式庫,因此每個應用程式都只需載入要使用的 API 部分。
- (選用) 將專案設為使用 v3 外部。
v3 外部可用於使用 Closure Compiler 驗證程式碼,或是在 IDE 中觸發自動完成功能。進一步瞭解進階編譯和外部服務。
- 測試並反覆修正。到目前為止,你還有一些工作要做,但好消息是,你現在已準備好改用全新的第 3 版地圖應用程式!
Maps JavaScript API 3 版的變更
規劃遷移作業前,請先花點時間瞭解 Maps JavaScript API 第 2 版與 Maps JavaScript API 3 版之間的差異。最新版本的 Maps JavaScript API 完全是以零開始編寫而成,但著重於著重於新型 JavaScript 程式設計技術、增加程式庫使用量和簡化的 API。
API 中新增了許多新功能,另有多項您熟悉的功能甚至有所變更。本節將重點介紹這兩個版本的主要差異。
第 3 版 API 中的部分變更包括:
- 簡化的核心程式庫。許多補充函式已移至程式庫,因此可縮短 Core API 的載入和剖析時間,讓地圖在任何裝置上都能快速載入。
- 改善幾種功能 (例如多邊形轉譯和標記位置) 的效能。
- 針對用戶端用戶端用量限制及公司防火牆使用的共用位址,提供用戶端使用限制這項新方法。
- 新增對多個新式瀏覽器和行動瀏覽器的支援。移除對 Internet Explorer 6 的支援。
- 移除許多一般用途輔助類別 (
GLog
或 GDownloadUrl
)。目前,許多卓越的 JavaScript 程式庫都提供類似的功能,例如 Closure 或 jQuery。
- 街景服務導入了 HTML5 技術,因此在任何行動裝置上都能載入這項服務。
- 自行標示「自訂街景服務」全景圖,方便您分享滑雪坡道、待售房屋或其他有趣的地點全景。
- 樣式化地圖自訂功能可讓您變更基本地圖上元素的顯示方式,以符合自己的獨特視覺樣式。
- 支援多種新服務,例如 ElevationService 和 距離矩陣。
- 更完善的路線規劃服務包括替代路線、路線最佳化 (旅客銷售問題概略的解決方案)、單車路線 (包含單車圖層)、大眾運輸路線和可拖曳的路線。
- 更新的 Geocoding 格式,能夠提供比 Geocoding API v2 所提供的
accuracy
值更準確的類型資訊。
- 在單一地圖上支援多個資訊視窗
新的金鑰
Maps JavaScript API 3 版使用第 2 版的全新金鑰系統。您的應用程式可能已採用第 3 版金鑰,因此無須變更。如要進行驗證,請查看您載入 Maps JavaScript API 的網址,並查看其 key
參數。如果鍵/值開頭為 'ABQIAA',代表您使用的是 v2 金鑰。如果您有 v2 金鑰,就必須在遷移過程中升級至 v3 金鑰,這麼做會:
載入 Maps JavaScript API 第 3 版時,系統會傳送金鑰。進一步瞭解如何產生 API 金鑰。
請注意,如果您是 Google Maps API for Work 客戶,使用的用戶端 ID 可能是 client
參數,而不是 key
參數。Maps JavaScript API 3.0 版仍支援用戶端 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 地圖平台付費方案) 確認提供
client
參數,如《Google 地圖平台付費方案開發人員指南》所述。
- 移除
v
參數以要求最新的發布版本,並根據 v3 版本管理配置,變更這個值。
- (選用) 將
hl
參數替換為 language
,並保留其值。
- (選用) 新增
libraries
參數以載入選用程式庫。
在最簡單的情況下,v3 啟動條件只會指定 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 預設會將所有物件放置在全域命名空間中,這可能會導致命名衝突。在 v3 中,所有物件都位於 google.maps
命名空間中。
將應用程式遷移至 v3 時,您必須變更程式碼才能使用新命名空間。但很遺憾地,在搜尋「G」時,會用「google.maps."win'」做為完整的程式碼執行方式,但查看程式碼時也適合採用這項規則。以下列舉第 2 版和第 3 版中同等類別的範例。
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.0 版中沒有平行功能:
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 的位址已變更。
- 第 3 版不再需要使用
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.0 版和第 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.');
});
移除事件接聽程式
基於效能考量,建議在不再需要時移除事件監聽器。移除事件監聽器在第 2 版和第 3 版中的運作方式相同:
- 建立事件監聽器時,系統會傳回不透明物件 (在第 2 版中GEventListener,在第 3 版中為 MapsEventListener)。
- 如要移除事件監聽器,請將這個物件傳送至
removeListener()
方法 (在 v2 中為 GEvent.removeListener()
,或在第 3 版中為 google.maps.event.removeListener()
) 以移除事件監聽器。
監聽 DOM 事件
如果想擷取並回應 DOM (文件物件模型) 事件,v3 會提供 google.maps.event.addDomListener()
靜態方法,等同於 v2 中的 GEvent.addDomListener()
方法。
在事件中使用傳遞的引數
UI 事件通常會傳送事件引數,讓事件監聽器可以存取。第 3 版中的大部分事件引數都已簡化,不再與 API 中的物件更加一致。(詳情請參閱 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 自訂這些控制項的顯示方式。
控制項類型的變更
第 3 版 API 對 control
類型進行了一些變更。
- 第 3 版 API 支援其他地圖類型,包括地形地圖和新增自訂地圖類型的功能。
- 第 2 版階層控制項已無法使用 (
GHierarchicalMapTypeControl
)。您可以使用 google.maps.MapTypeControlStyle.HORIZONTAL_BAR
控制項達到類似的效果。
- 在第 3 版中,
GMapTypeControl
提供的水平版面配置不適用於第 2 版。
在地圖中加入控制項
有了 Maps JavaScript API 2 版,您可以透過地圖物件的 addControl()
方法,將控制項加入地圖。在第 3 版中,您必須修改相關聯的 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 版中有大幅變更。在第 2 版中,addControl()
方法採用選用第二個參數,讓您指定控制項相對於地圖角落的位置。
在第 3 版中,您可以透過控制項選項的 position
屬性設定控制項的位置。這些控制項的位置並非絕對位置,因此 API 會以「限制」的方式靈活控制控制項,在指定控制項內 (例如地圖大小) 的現有地圖元素周圍移動。這樣可以確保預設控制項與控制項相容。
詳情請參閱「第 3 版中的控制定位」。
下列程式碼重新設定上述範例的控制項位置:
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);
重疊說明
疊加層會反映您在「新增」至地圖中的物件,以標示物件的點、線、區域或集合。
新增與移除疊加層
疊加層代表的物件類型在 v2 和 v3 之間相同,但處理方式不同,
v2 API 中的疊加層透過 GMap2
物件的 addOverlay()
和 removeOverlay()
方法,在地圖上新增及移除。在第 3 版中,您可以透過相關疊加層選項類別的 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
建構函式的選項。在第 3 版中,以這種方式指定的圖示應將 icon
屬性設為 Icon
類型的物件。v3 不支援標記陰影。
以下範例顯示了澳洲邦迪海灘的海灘旗幟,其中的圖示透明部分是不可點擊的:
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);
編碼折線
第 3 版不支援透過直接從編碼折線建立 Polyline
物件的功能。而幾何圖形程式庫也提供對折線進行編碼及解碼的方法。如要進一步瞭解如何載入這個程式庫,請參閱 3 版 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);
多邊形
「多邊形」指的是頭尾相連的多角線段所構成的封閉型區塊。與 Polyline
物件非常類似,Polygon
物件則包含按順序排列的一系列點。v3 Polygon
類別與 v2 GPolygon
類別完全相同,但重要的差別在於您必須在路徑結尾重複起始起始頂點以關閉迴圈。第 3 版 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);
如需更多進階繪圖功能,請參閱 v3 說明文件中的繪圖程式庫。
資訊視窗
InfoWindow
會在地圖上方的浮動視窗中顯示內容。第 2 版和第 3 版資訊視窗有幾項主要差異:
- 第 2 版 API 在每個地圖上僅支援
GInfoWindow
,而 v3 API 則在每個地圖上支援多個並行的 InfoWindow
。
- 當您按一下地圖時,第 3 版
InfoWindow
會保持開啟。當您點擊地圖時,第 2 版 GInfoWindow
會自動關閉,您可以在 Map
物件上新增 click
事件監聽器,藉此模擬 v2 行為。
- v3 API 無法為分頁式
InfoWindow
提供原生支援。
區域疊加層
如要在地圖上放置圖片,請使用 GroundOverlay
物件。在 v2 和 v3 中,GroundOverlay
的建構函式基本上相同:指定圖片網址和圖片邊界做為參數。
下方範例將新北市的紐瓦勒地圖在地圖上疊加在地圖上:
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);
地圖類型
第 2 版和第 3 版提供的地圖類型略有不同,但所有基本地圖類型都可用於這兩種 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 API 中做為地圖類型使用,但可設為此範例中顯示的自訂地圖類型。
- 第 3 版中沒有可取代
G_SATELLITE_3D_MAP
類型的特殊地圖類型。您可以改用這個程式庫,在 Google 地圖 3.0 版中整合 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 檔案,您必須將其公開。在第 3 版中,系統會使用 KmlLayer
的執行個體顯示這些資料格式,並取代來自 v2 的 GGeoXml
物件。
v3 API 在轉譯 KML 時更具彈性,可讓您隱藏 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 不同,第 3 版中的 TrafficLayer
建構函式沒有選項。第 3 版不支援事件。
服務
Geocoding
Maps JavaScript API 提供 geocoder
物件,用於在使用者輸入內容中動態處理地理編碼地址。如果您要對已知的靜態地址進行地理編碼,請參閱 Geocoding API 說明文件。
Geocoding API 大幅升級及強化功能,加入新功能並變更資料呈現方式。
第 2 版 API 的 GClientGeocoder
提供兩種轉送/反向地理編碼的方法,以及其他影響地理編碼執行方式的方法。相反地,v3 Geocoder
物件只會提供 geocode()
方法,該方法使用包含輸入字詞 (以地理編碼要求物件的形式) 和回呼方法的物件配置。視要求是否包含文字 address
屬性或 LatLng
物件而定,Geocoding API 會傳回正向或反向的地理編碼回應。只要將其他欄位傳送至地理編碼要求,即可影響地理編碼的執行方式:
- 加入文字
address
時,會觸發正向地理編碼,相當於呼叫 getLatLng()
方法。
- 加入
latLng
物件會觸發反向地理編碼,相當於呼叫 getLocations()
方法。
- 加入
bounds
屬性即可啟用可視區域偏誤,相當於呼叫 setViewport()
方法。
- 加入
region
屬性即可啟用區域代碼偏誤,相當於呼叫 setBaseCountryCode()
方法。
第 3 版的地理編碼回應與第 2 版的回應非常不同。v3 API 會將第 2 版使用的巢狀結構替換成更容易剖析的平面結構,此外,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 版會將 v2 中的 GDirections
類別替換為 DirectionsService
類別,用來計算路線。
第 3 版的 route()
方法會取代第 2 版 API 的 load()
和 loadFromWaypoints()
方法。這個方法使用單一 DirectionsRequest
物件常值,其中包含輸入字詞,以及收到回應時執行的回呼方法。此物件常值可能會提供選項,類似於 v2 中的 GDirectionsOptions
物件常值。
在 Maps JavaScript API 第 3 版中,提交路線規劃要求的工作已和轉譯要求的工作分開,後者現在是透過 DirectionsRenderer
類別處理。您可以將 DirectionsRenderer
物件連結至任何地圖,或 DirectionsResult
物件的 setMap()
和 setDirections()
方法。由於轉譯器是 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 不同,第 3 版 API 在瀏覽器中也支援街景服務。
街景服務圖像支援使用 v3 中的 StreetViewPanorama
物件或 v2 中的 GStreetviewPanorama
物件。這些類別有不同的介面,但運作方式相同:連結 div
容器與街景服務圖像,以及指定街景服務全景的位置和視角 (POV)。
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 來顯示街景服務全景。以下程式碼示範如何將街景服務全景分隔為個別的 div,藉此模擬 v2 的行為。
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);
}