基於地圖的搜尋需要有一張地圖,還需具備搜尋相關位置的能力。幸運的是,Virtual Earth 地圖控制項為我們同時提供了這兩個必要條件。其中最可喜的是,我們只需使用 HTML、JavaScript 和一點點 CSS 即可構建一個基於地圖的搜尋系統。
VEMap 控制項不僅可以顯示我們的地圖,它還提供了四種不同的執行搜尋的方法:
• |
在 local.live.com 上可用的 What/Where 控制項在基本的 VEMap 控制項中也可用。我們可以增加一行 JavaScript 代碼來開啟此控制項。 |
• |
FindLocation() 方法用於執行位置搜尋。如果找到匹配位置,地圖會自動重新置中於該位置並放大到適當的層級。 |
• |
FindNearby() 方法用於執行“what”搜尋以尋找位於當前地圖中心附近的企業。此搜尋與 local.live.com 使用相同的黃頁資料庫。 |
• |
Find() 方法可讓您最大程度地對搜尋進行控制,您既可以指定搜尋內容,也可指定搜尋範圍。還可以在 JavaScript 回呼函數中接收搜尋結果。 |
通過選擇適當的 Find 方法,您可以構建一個功能完備的基於地圖的搜尋應用程式。
在探討用於尋找位置的各種選項之前,讓我們先來看看基本的 Virtual Earth 地圖:
<html><head><script src="http://dev.virtualearth.net/mapcontrol/v4/mapcontrol.js"></script><script> var map; function OnPageLoad() { map = new VEMap('myMap'); map.LoadMap(); }</script><body onload="OnPageLoad();"> <div id="myMap" style="position:relative;width:600px;height:400px;"></div></body></html>
程式清單 1 基本頁面 (Find.html)
如果在瀏覽器中載入此頁面,您應看到一張帶有基本 Virtual Earth 導航儀表板的美國地圖。
What/Where 控制項
只需開啟 what/where 控制項即可利用尋找功能,這是最簡單的方法。將下面這行代碼添加到 OnPageLoad() 方法的末尾:
map.ShowFindControl();
程式清單 2 開啟 Find 控制項
如果在瀏覽器中載入修改後的頁面,您應在右上方看到 What/Where 控制項:
圖 1 What Where 控制項
如果在“where”(搜尋範圍)框中鍵入一個地址(如 Denver),然後單擊“Find”(尋找),地圖會自動重新置中於所處位置。如果 Virtual Earth 無法找到完全符合的項,您將看到一個消除二義性的彈出式對話方塊:
圖 2 消除二義性對話方塊
只需單擊所需的位置,地圖即會重新置中並縮放到適當的層級:
圖 3 重新置中後的地圖
如果使用者在“What”(搜尋內容)框中輸入了資訊,則會看到與在黃頁中搜尋的輸入資訊匹配的一組圖釘。 例如,我們可以在“Vail, Colorado”(科羅拉多州的維爾)尋找“coffee”(咖啡):
圖 4 What 和 Where
當然,What/Where 控制項也存在一些缺陷。首先,該控制項相當寬。地圖的寬度必須至少為 635 個像素才能在地圖上顯示整個控制項。可以通過尋找相關的 CSS 條目進行樣式調整,但此項功能既不容易公開也不直接支援。另一問題是對搜尋的定義相當不精確。也就是說,使用者可以採用任何格式輸入地址,而 Virtual Earth 會做出最佳推斷。我們可以通過建立自己的尋找控制項來克服上述兩種局限性。
返回頁首
FindLocation 方法
FindLocation() 方法非常簡單而且便於使用。我們只需傳入一個包含地址的字串即可。在本例中,我們想強制使用者輸入一個郵遞區號。因此,我們將要建立一個面板,其中包含一個文字框和一個尋找按鈕。另外,我們還要將尋找按鈕連結到我們的 FindLocation 方法。
首先,我們需要增加一些 HTML。請將以下 div 添加到 html 檔案體中:
<div id="SearchPanel" > <table border=0> <tr><td bgcolor='#C0C0CF'><p align='center'>Search</p></td></tr> <tr><td><p align='center'> Zip Code: <INPUT id="txtZip" type="text" value="" name="txtZip"> </td></tr> <tr><td bgcolor='#E0E0E0'><p align='center'> <input type="button" value="Search" onclick="DoFind();" id="Search" name="Search" /> </td></tr> <table></div>
程式清單 3 添加面板
接下來,我們需要添加一些樣式資訊,以使我們的搜尋控制項更好看一些。請將以下指令碼塊添加到頁面的頭部:
<style type="text/css" media="screen"> #SearchPanel { width: 150px; border-style: solid; border-width: 1px; border-color: lightgray; background: white; }</style>
程式清單 4 尋找框樣式設計
接下來,我們需要將尋找面板附加到地圖上並將其定位在所需位置。請用以下代碼替換您的 OnPageLoad() 方法:
function OnPageLoad(){ map = new VEMap('myMap'); map.LoadMap(); var search = document.getElementById('SearchPanel'); map.AddControl(search); search.style.left = "475px"; search.style.top = "5px";}
程式清單 5 附加搜尋面板
最後,我們需要構建 DoFind() 方法。請將以下代碼添加到指令碼塊中:
function DoFind(){ map.FindLocation(document.getElementById('txtZip').value);}
程式清單 6 實現 FindLocation
如果現在載入我們的應用程式,應在右上方看到我們自己自訂的尋找框。請輸入自己想要的郵遞區號,然後單擊尋找按鈕,看看會發生什麼情況:
圖 5 工作中的 FindLocation
可以添加驗證代碼以確保使用者輸入有效郵遞區號,不過我要將此當作練習留給讀者。
返回頁首
FindNearby 方法
我們列表中的下一項任務是實現我們自己的“what”搜尋。要實現“what”,需要替換我們搜尋面板中的 html:
<div id="SearchPanel" > <table border=0> <tr><td bgcolor='#C0C0CF'><p align='center'>Search</p></td></tr> <tr><td><p align='center'> Business: <INPUT id="txtBiz" type="text" value="" name="txtBiz"> </td></tr> <tr><td bgcolor='#E0E0E0'><p align='center'> <input type="button" value="Search" onclick="DoFind();" id="Search" name="Search" /> </td></tr> <table></div>
程式清單 7 What 文字框
我們還需要更改 DoFind() 方法:
function DoFind(){ map.FindNearby(document.getElementById('txtBiz').value);}
程式清單 8 使用 FindNearby
請注意,FindNearby() 方法看起來幾乎與 FindLocation() 方法完全一樣。
如果現在在瀏覽器中載入我們的頁面,即可執行“what”搜尋來尋找某個企業:
圖 6 FindNearby 方法
在運行搜尋之前,可能需要放大所關注的地區。預設的地圖視圖將顯示整個美國版圖,並在地圖中心點附近執行搜尋。
返回頁首
Find 的全部功能
執行搜尋的最後一個選擇可以讓您同時對搜尋過程和結果進行最大程度的控制。首先,我們只需將 FindLocation 和 FindNearby 搜尋合并到單個搜尋方法中。
第一步,將“Business”(企業)和“Zip”(郵編)兩個文字框都添加到 html 中:
<div id="SearchPanel" > <table border=0> <tr><td bgcolor='#C0C0CF'><p align='center'>Search</p></td></tr> <tr><td><p align='center'> Zip Code: <INPUT id="txtZip" type="text" value="" name="txtZip"> </td></tr> <tr><td><p align='center'> Business: <INPUT id="txtBiz" type="text" value="" name="txtBiz"> </td></tr> <tr><td bgcolor='#E0E0E0'><p align='center'> <input type="button" value="Search" onclick="DoFind();" id="Search" name="Search" /> </td></tr> <table></div>
程式清單 9 完整的搜尋面板
下一步,我們需要再一次替換我們的 DoFind() 方法:
function DoFind(){ var where = document.getElementById('txtZip').value; var what = document.getElementById('txtBiz').value; map.Find(what, where, 1);}
程式清單 10 含有 what 和 where 的 Find 方法
現在,如果載入我們的網頁,應該會看到 what 和 where 兩個文字框。
圖 7 使用 Find 進行搜尋
此時,我們的應用程式與使用內建 what/where 控制項的初始版本完全等同。
返回頁首
處理結果
我們可能不想自動顯示結果而是希望另外執行某種篩選或處理。甚至可能想要將結果顯示在一個新的面板中。幸運的是,Find() 方法與我們所選擇的其他方法都不一樣,它允許我們定義一個 JavaScript 回呼函數。尋找完成後將會啟用該回調方法,從而使我們可以對結果進行訪問。
根據調用 Find() 的具體方式,我們可能會收到兩種不同類型的結果:
• |
如果 Find 方法返回“where”,我們將收到一個 VESearchResult 對象。每個對象均包含一個 ID 值和一對緯度/經度。 |
• |
如果 Find 方法返回“what”,我們將收到一個 VEFindResult 對象。每個對象均包含若干屬性,包括 Name、Description、Phone 和一對緯度/經度。 |
由於我們無法確定將會返回哪種類型的結果,因此我們需要對結果類型進行區分。VESearchResult 始終都會有一個非空的 ID 欄位,而 VEFindResult 始終都會有一個非空的名稱欄位。
返回頁首
建立結果檢視
我們想要將結果顯示在地圖極右側的表中。需要添加一些 html 和 css 來定義該表。首先將以下 <div> 標記添加到頁面體中:
<div id="SearchResults" ></div>
程式清單 11 SearchResults Div
接下來添加一些 CSS 以定義該 div。請將以下新樣式添加到樣式部分:
#SearchResults{ display: none; width: 325px; border-style: solid; border-width: 1px; border-color: lightgray; background: white;}
程式清單 12 搜尋結果的 CSS
最後,我們想要將該 div 作為一個控制項附加到我們的地圖對象上。讓我們回到 OnPageLoad() 函數,並在該函數的末尾添加一些新代碼:
var results = document.getElementById('SearchResults');map.AddControl(results);results.style.left = "640px";results.style.top = "5px";map.ShowDisambiguationDialog(false);
程式清單 13 建立搜尋結果視圖
請注意,與使用 What/Where 面板一樣,在將該控制項添加到地圖後,我們必須設定其位置。同樣,我們也會關閉自動排除二義性功能。如果省略最後這一行,我們將無法使用我們的結果,因為在執行回調之後將會強制使用者確定一個位置。關閉排除二義性即表示我們告知地圖自動選擇所返回的第一個位置。
返回頁首
修改 DoFind 方法
接下來,我們必須向 Find() 調用添加一個額外的參數。此額外參數用於標識該 JavaScript 回調方法:
function DoFind(){ var where = document.getElementById('txtZip').value; var what = document.getElementById('txtBiz').value; map.Find(what, where, 1, ProcessResults);}
程式清單 14 DoFind
返回頁首
ProcessResults 方法
最後,我們需要建立我們的 ProcessResults() 方法。我們要建立一個表並將其放到 SearchResults <div> 中。
function ProcessResults(findResults){ var results ="<table><tr><td colspan=3 align='center'>Find results</td></tr>"; results += "<tr><td>Name</td><td>Description</td><td style='width: 100px;'>Phone</td></tr>"; var numresults = 5; numresults = Math.min(numresults, findResults.length); for (r=0; r<numresults; r++) { results += "<tr><td>"; if (findResults[r].Name!=null) //VEFindResult 對象 { results += findResults[r].Name + "</td><td>"; results += findResults[r].Description + "</td><td style='width: 100px;'>"; results += findResults[r].Phone; } else { results += "Unknown</td><td>N/A"; } results += "</td></tr>"; } results += "</table>"; var resultPane = document.getElementById('SearchResults'); resultPane.style.display = 'block'; resultPane.innerHTML = results;}
程式清單 15 ProcessResults 方法
如果現在載入我們的頁面,則應該能夠輸入郵遞區號和企業並看到結果:
圖 8 最終視圖
儘管我們的基本應用程式可以正常工作,不過我們始終都可以添加更多的功能。例如,可以添加驗證以確保使用者只能輸入郵遞區號。還可以使我們的表顯示更多或更少的結果,甚至允許使用者翻頁到下一組結果。
返回頁首
結束語
內建於 VEMap 控制項中的多種搜尋選擇為您設計基於地圖的搜尋提供了很大的靈活性。無論您想要進行簡單搜尋還是要對使用者輸入進行複雜的控制,只需使用 JavaScript、CSS、HTML 和 Virtual Earth SDK 就可以辦到。
本文作者是來自 Infusion Development 的 Robert McGovern MVP (Virtual Earth/MapPoint)。
原文地址:http://www.microsoft.com/china/MSDN/library/Windev/windowslive/bb259692.mspx?mfr=true
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1560744