0. 摘要
地圖應用是大流量應用,如果頻繁重新整理頁面,造成的資料傳輸也必然是很大的,這在你的網絡不是很好的時候,你就醉了,這時候便是 AJAX 顯現優勢的時候了。這裡我們把 AJAX 應用在地圖搜尋中,下面看看怎麼做到的吧!
當然,AJAX 在執行的時候,如果網絡不好,同樣會讓使用者感到點選了觸發 AJAX 的按鈕,卻沒有反應!是以可以在處理過程中,添加一個進度條。現實項目中,要根據情況選擇最合适項目的技術,是業務驅動技術,而不是反過來!
1. 什麼是AJAX ,什麼作用
AJAX,全稱是Asynchronous JavaScript + XML,它可以向伺服器請求額外的資料而無需解除安裝頁面,帶來更好的使用者體驗。雖然名字中包含XML,但是AJAX的通信實際上與資料格式無關,這種技術就是無需重新整理頁面即可從伺服器取得資料,但不一定是XML資料。
使用AJAX不僅要處理浏覽器的相容問題,還要處理與伺服器通信過程中的狀态變化問題。為了避免這些繁雜的與事務無關的事情,使用一種架構來處理這些繁雜的事情,很有必要,JQuery等很多架構都可以做到。
2. 添加查詢元件
我們可能想給系統加上查詢地理事物的功能,而前面我們提到最好是在不重新整理的情況下進行查詢和結果展示,這裡便是一個AJAX技術很好的應用點!首先我們要在HTML檔案中添加搜尋框,然後在JS檔案中編寫點選按鈕的事件,事件進行中便包含一些AJAX技術,用來查詢資料庫。
2.1 在 map.html 添加搜尋框
<div id="search_group" class="search_group">
<input id="search_input" class="search_input">
<button id="search_button" class="search_button" type="button">搜尋!</button>
</div>
這段代碼加入到 id 為”map”的 div 裡邊,讓其為第一個子元素。這裡每個元素都有兩個屬性:id 和 class ,id 是為了使用 JavaScript 取用使用者輸入文字的(getElementById), class 是 css 類,定義了相應元素的外觀。
2.2 在 map_style.css 添加搜尋框樣式
我們不在元素内部直接寫 style ,是為了代碼容易維護,如果元素外觀顯示不正确或者需要修改,可以直接在 css 檔案直接修改,不用在 HTML中查找,這樣有利于内容(HTML)、外觀(CSS)和行為(JavaScript)的解耦,最終提高代碼的可維護性。
在 map_style.css 中添加的内容如下:
/**
* search group css
*/
.search_group, .search_input, .search_button{
position:absolute;
z-index: ;
top: px;
}
.search_input{
width:px;
height:px;
left:px;
}
.search_button{
width:px;
height:px;
left:px;
}
這裡我們使用了絕對定位: position: absolute; ,這是相對于第一個父元素的定位,這裡是 body 元素,這種定位方式使用 left、right、top 和 bottom來進行定位。這種定位方式的元素是浮動的,不影響其它元素的位置,這樣我們才能将搜尋框覆寫在地圖之上,而不會擠掉地圖的一行位置。
我們可以比較一下注釋掉 position: absolute; 這句,比對一下結果:
– 圖1 注釋之前
– 圖2 注釋之後
一個是浮動,一個是并排!
3. 整合 AJAX 和查詢元件
為了避免處理浏覽器間的相容問題,也為了簡化代碼,我們使用 JQuery 提供的 AJAX 元件。
3.1 在map_utils.js 中添加處理事件
首先擷取 button,然後注冊 button 的 click 事件,click 事件是發送 AJAX 請求。添加的代碼如下:
/**
* 處理使用者點選搜尋按鈕的事件
* 擷取輸入,如果為空,什麼都不做;如果不為空,首先檢查輸入,然後發送AJAX請求(使用JQuery)
*/
function sendQuery(){
var search_input = document.getElementById("search_input").value;
$.ajax({
url: "http://127.0.0.1/csdn_blog_about/getQueryData.php?search_input=" + search_input,
success: function(result){
var jsonResult = JSON.parse(result);
//do something
}
});
}
var search_button = document.getElementById("search_button");
search_button.onclick = sendQuery;
這時候,當點選按鈕時候,就會發送 AJAX 請求,并将傳回的資料解析成 JavaScript 的對象,然後進行操作!
這裡特别指出一點,AJAX 是不能跨域的,也就是說, AJAX 接受請求的檔案位址必須和 送出請求的位址是同一個域名下的!這一點非常重要,即使是本地的檔案系統,如:“D://map.html”請求本機如 “127.0.0.1/getQueryData.php” 也是不能請求成功的。必須将 map.html 和 getQueryData 放于一個 web 目錄下,但并一定在一個子檔案夾内。
例如,我讓 getQueryData.php 傳回的是一個 GeoJSON 字元串,其中包含 name、content 和坐标等屬性,這樣我們可以首先獲得搜尋的結果的坐标值,然後平移到相應的位置,然後再在相應位置彈出一個 Popup,顯示搜尋結果的 name 等屬性。
/**
* 根據傳來的參數,平移到相應坐标,然後展示相應内容
* 參數為 name(搜尋結果的名稱),content(搜尋結果的内容),coordinates(搜尋結果的坐标)
*/
function zoomAndDisplay(name, content2, coordinates){
try{
//zoomTo(coordinates);
var view = new ol.View({
center: ol.proj.transform(coordinates, 'EPSG:4326', 'EPSG:3857'),
zoom:
});
map.setView(view);
//display [name, content]
content.innerHTML = '<p>名稱:<code>' + name + '</code></p><p>内容:'+ content2 + '</p>';
var crd = ol.proj.transform(coordinates, 'EPSG:4326', 'EPSG:3857');
overlay.setPosition(crd);
map.addOverlay(overlay);
}
catch(ex){
console.log(ex.message);
}
}
将這段函數定義放于 map_utils.js 中,然後再在 sendQuery 函數中調用此函數。此處要注意,我刻意将兩個函數分開,其實是可以寫在一起的,why? 其實是為了“解耦應用邏輯 / 事件處理程式”,這麼做首先,可以讓你更容易更改觸發特定過程的事件,如将原來滑鼠觸發的事件,現在添加鍵盤觸發;其次,可以在不附加到事件的情況下測試代碼,使其更容易建立單元測試或者是自動化應用流程!
最後,結果是這樣的!
圖3 點選之前
圖4 輸入并點選之後
3.2 關于投影坐标系
注意 OpenLayers 的
new ol.source.MapQuest({layer: 'sat'})
這個圖層的預設投影坐标系是
'EPSG:3857'
, 而一般我們用的比較廣泛的是
'EPSG:4326'
,也就是傳說中的
WGS84
坐标系。
是以當使用
map.setView(view)
和
overlay.setPosition(coordinate)
時候,要注意将我們使用的坐标轉換到相應的參考系之下:
ol.proj.transform(coordinates, 'EPSG:4326', 'EPSG:3857');
。
4. 總結
前面提到,AJAX 相對于傳統的表單送出,省去了重新整理網頁,但是在發送和接受結果時候,頁面沒有任何變化,如果網速很慢或者處理事件很長,很容易造成使用者誤解,以為 AJAX 請求并沒有發生。是以,實際項目中,我們應該添加一些動畫等效果,提示使用者正在進行中,無需重複點按等。
将 HTML、CSS 和 JavaScript 解耦,不僅有利于錯誤發生時,錯誤的快速定位;而且有利于項目日後的維護。是以應該注意程式的可維護性和可擴充性,同時良好的注釋和變量命名,更增加了代碼的可讀性,變量命名沒有必要擔心長度,因為長度問題可以通過後處理和壓縮來緩解。
AJAX 用在地圖等重新整理代價很大,或者 web 應用程式模拟桌面應用程式時非常優雅。
5. 附錄代碼下載下傳
5.1 下載下傳連結
點選源碼下載下傳連結進行下載下傳, 我把代碼放在百度雲盤裡邊了。
5.2 說明
代碼正常運作必須有的先決條件:
1、php 檔案必須和 js 檔案放于一個域名下面,也就是伺服器指定的 web 路徑下面,不要求一個子檔案夾。主要是 AJAX 的安全性限制,不能跨域通路;
2、要求伺服器是 Apache httpd 或者 IIS 附加 php 擴充,也就是說要支援 php;
3、考慮簡化樣式代碼,處理浏覽器樣式相容問題,我們以後可能使用 bootstrap 來開發,這篇文章肯能沒有用到,但是以後可能會用到;
4、文中用到了 JQuery 庫,是以檔案中要引用該庫;
5、代碼連結中以上的 bootstrap 和 JQuery 都已經包含!