標籤:style blog http java os 使用 io strong ar
使用Google地圖API搜尋功能
由於工作關係,最近這兩天研究了下Google地圖API,要實現地圖位置搜尋功能,顯示搜尋結果並能在地圖上標記下來,剛開始還考慮使用51ditu,出於搜尋索引鍵分詞等方面考慮,最後還是決定使用Google地圖,一直也都是那麼的崇拜Google的大神,這次就來體驗一翻~
在Google地表徵圖記定位到一點
剛開始是實現在Google地圖上定位一點的功能,API介面裡GMap2類有一個setCenter(center:GLatLng, zoom?:Number, type?:GMapType)方法可以設定地圖中心,GLatLng參數以經度和緯度表示的地理座標點,zoom和type分別為縮放層級和地圖類型的選擇性參數,GLatLng經緯度座標點可以通過GClientGeocoder類的getLatLng方法獲得,getLatLng方法傳入地址關鍵字參數,在回呼函數裡傳遞找到的第一個經緯度座標點,如果沒有找到錨點則為null,這樣我們就能根據GLatLng經緯度座標點建立一個GMarker標記並在地圖上顯示出來。
搜尋定位到多個點
根據關鍵字定位到會存在一個問題,假如搜尋索引鍵在地圖上有多個點的話,那麼返回的第一個經緯度座標點不一定就是你所要找的地址,這個時候就有必要返回多個搜尋結果點,然後再能讓使用者選擇。剛開始我還以為Google地圖API裡沒有提供返回多個搜尋結果的介面,讓老萍各一強銀說就跑到了Google AJAX Search API,不過那裡確實有實現搜尋返回多個結果的樣本。今天仔細看了下Google地圖API,發現它裡面本身是提供搜尋功能的,我想AJAX Map Search Solution只是自訂實現封裝好了類。其實,在建立GMap2執行個體時可指定GMapOptions參數,裡面的GGoogleBarOptions屬性即為搜尋控制項的選項,然後再調用enableGoogleBar()方法就會為地圖啟用整合搜尋控制項,GGoogleBarOptions 類屬性如下:
屬性 |
類型 |
說明 |
showOnLoad |
Boolean |
當設定為 true 時,該屬性顯示 GoogleBar 中的搜尋方塊(如果啟用了控制項並載入了地圖)。預設情況下,控制項中的搜尋方塊是隱藏的,只有當點擊該控制項的放大鏡時才會展開。 (自 2.95 開始) |
linkTarget |
GGoogleBarLinkTarget |
該屬性允許指定嵌入 GoogleBar 的搜尋結果中的連結目標。預設值為 G_GOOGLEBAR_LINK_TARGET_BLANK,該預設值指定這些連結將在新視窗中開啟。 (自 2.95 開始) |
resultList |
GGoogleBarResultList or Element |
該屬性可讓您指定 GoogleBar 的搜尋結果列表的樣式,該樣式可能為以下樣式的一種:G_GOOGLEBAR_RESULT_LIST_INLINE(預設樣式)將結果清單放入搜尋方塊上的表中;G_GOOGLEBAR_RESULT_LIST_SUPPRESS 使用“下一個”/“上一個”按鈕替換該列表;傳遞塊層級的 DOM 的 Element 將列表放入您選擇的容器(通常為 <div> 元素)中。 (自 2.95 開始) |
suppressInitialResultSelection |
Boolean |
系統完成 GoogleBar 中的搜尋後就會在其資訊視窗中顯示第一個結果(這是預設行為),該屬性抑制這種行為。 (自 2.95 開始) |
suppressZoomToBounds |
Boolean |
該屬性還抑制完成 GoogleBar 中的搜尋後自動平移和縮放以適合結果集的操作。(該屬性抑制預設行為。) (自 2.95 開始) |
onIdleCallback |
Function |
該屬性指定 GoogleBar 完成搜尋且搜尋結果關閉時要調用的回呼函數。 (自 2.95 開始) |
onSearchCompleteCallback |
Function |
該屬性指定 GoogleBar 完成搜尋且搜尋結果完全顯示時要調用的回呼函數向該函數傳遞與搜尋控制項相關的 GlocalSearch 對象。在結果放到地圖上或結果清單中之前調用該回呼函數。 (自 2.95 開始) |
onGenerateMarkerHtmlCallback |
Function |
此屬性可讓您指定開啟搜尋結果標記的資訊視窗時要調用的回呼函數。應該向該函數先後傳遞 GMarker、產生的 HTML 字串和 GlocalSearchResult,並且該函數必須返回要顯示在資訊視窗中的已修改 HTML 字串。 (自 2.95 開始) |
onMarkersSetCallback |
Function |
該屬性可讓您指定 GGoogleBar 完成建立標記並將標記放到地圖上時要調用的回呼函數。必須向該函數傳遞一個表格對象數組 {result: GlocalSearch, marker: GMarker}。 (自 2.95 開始) |
點擊搜尋結果點資訊視窗"錯位"問題
問題是這樣的,點擊返回搜尋結果列表時地圖會定位到當前點,並且會用資訊視窗標註這一點,但不知道Google是為了開啟的資訊視窗完全可見還是做了什麼特殊判斷,會使得當前標註這一點不能地圖裡置中,致使標註點位移資訊視窗顯示不完全。由於搜尋結果是直接指定resultList元素容器來接收存放的,所以我並不知道在點擊事件裡對Google地圖做了什麼樣的操作,可能查看gmlocalsearch.js源碼會瞭解一些詳情。回到問題的原委來,我只需要擷取點擊的經緯度座標點就能把地圖位置置中,還好搜尋有個onSearchCompleteCallback完成時的回呼函數,並傳遞搜尋結果參數過來,那麼我就在每次搜尋完成把結果儲存在一個陣列變數裡,然後在點擊搜尋結果列表時擷取點擊元素的id索引號,於是就能擷取當前點擊的經緯度座標了,再調用setCenter就能根據座標點置中地圖,由於有資訊視窗,座標點置中不一定能讓資訊視窗完全可見,而應該是中偏下一些,調用map.panBy(new GSize(-40,100))方法以動畫方式平移指定的距離(左:40px,下:100px),需要注意Google地圖API裡很多方法都是以動畫方式,它內部可能是通過setTimeout來順延強制實現的,所以我這邊有時也要用setTimeout來順延強制,不然我設定的一些值會被Google的setTimeout順延強制的給覆蓋掉。
樣本原始碼:
<div id="googleSearch"></div>
<div id="googleResult" style="width:490px; margin:4px 0;"></div>
<div id="googleMap" style="width:490px; height:300px; border:solid 1px #ccc">loading...</div>
<link href="http://www.google.com/uds/css/gsearch.css" rel="stylesheet" type="text/css" />
<link href="http://www.google.com/uds/solutions/localsearch/gmlocalsearch.css" rel="stylesheet" type="text/css" />
<script src="http://ditu.google.cn/maps?file=api&v=2.x&key=ABQIAAAAzr2EBOXUKnm_jVnk0OJI7xSosDVG8KKPE1-m51RBrvYughuyMxQ-i1QfUnH94QxWIa6N4U6MouMmBA&hl=zh-CN" type="text/javascript"></script>
<script type="text/javascript">
var map = null;
var geocoder = null;
var mapReady = false;
var mapResult = [];
function initialize() {
if (GBrowserIsCompatible()) {
//搜尋結果元素
var resultElem = document.getElementById("googleResult");
//地圖容器元素
var mapElem = document.getElementById("googleMap");
// 指定執行個體化地圖選項
var options = {
//size : new GSize (338,353),
googleBarOptions : {
onSearchCompleteCallback : function(searcher) {
//設定結果
mapResult = searcher.results;
//統計結果數
//document.getElementById("sum").innerHTML = searcher.results.length;
//搜尋完成時候自動置中第一個結果
setTimeout(function() {autoCenter(0);},1000);
},
resultList : resultElem ,
maxCursorPages : 5 ,
suppressZoomToBounds : true
}
};
map = new GMap2(mapElem, options);
// 平移及縮放控制項(左上方)
map.addControl(new GLargeMapControl());
//比例尺控制項(左下角)
map.addControl(new GScaleControl());
//建立縮圖控制項(右下角)
var overviewMap = new GOverviewMapControl();
map.addControl(overviewMap);
//最小化隱藏縮圖控制項
setTimeout(function (){overviewMap.hide();},1000);
geocoder = new GClientGeocoder();
//為地圖啟用整合搜尋控制項GoogleBar(此句順序位置不可修改)
map.enableGoogleBar();
//自動置中結果點
window.autoCenter = function (resultIndex){
var result = mapResult[resultIndex];
if( result ) {
setTimeout(function() {
//構建以經度和緯度表示的地理座標點
var point = new GLatLng(result.lat,result.lng);
//設定中心點
map.setCenter(point);//map.panTo(point);
//以動畫方式平移指定的距離(左:40px,下:100px)
map.panBy(new GSize(-40,100));
},
500
);
}
}
//點擊搜尋結果事件
resultElem.onclick = function (e){
e = window.event || e;
var target = e.target || e.srcElement;
var trElem = target;
//擷取冒泡事件的TR層節點
while(trElem && trElem.tagName!="TR")
{
if(trElem.tagName=="TABLE") break;
trElem = trElem.parentNode;
}
if (trElem!=null)
{
//擷取點擊的結果索引
var resultIndex = trElem.id.substring(trElem.id.length-1);
//自動置中
autoCenter(resultIndex);
}
}
//初始化位置
var address = "廣東省廣州市天河區科韻路22號五華大廈";
if (geocoder) {
geocoder.getLatLng(
address,
function(point) {
if (point) {
map.setCenter(point, 18);
var marker = new GMarker(point);
map.addOverlay(marker);
marker.openInfoWindowHtml(address);
setTimeout(function (){map.panBy(new GSize(-10,120));},2500);
}
}
);
}
//擷取搜尋控制項
var searchBar = mapElem.lastChild;
//清空樣式
searchBar.style.cssText = "";
//改變搜尋控制項元素位置
document.getElementById("googleSearch").appendChild(searchBar);
}
}
window.onload = function(){
initialize();
document.body.onunload = GUnload;
mapReady = true;
}
</script>
[轉]使用Google地圖API搜尋功能