為什麼要使用地圖?
在這個信息時代,因特網承擔著一項重要的工作:開發應用程序來處理大量信息並有效地顯示信息。在處理地理數據時,最好的方法是用圖形顯示它。這種顯示方式已經在計算機上存在多年了,比如地理信息系統(GIS)和 Mapquest 等網站。但是,Google Maps 通過簡單易用的接口徹底革新了在線地圖的編程模型,使用戶能夠快速輕松地找到信息。通過使用 Google Maps,可以拖放和實時更新地圖,而不需要重新裝載 Web 頁面。現在,其他地圖站點(包括 Mapquest、Yahoo! 和 Microsoft)也開始采用 Google Maps 創建的模型了。
本文的目的
盡管目前有許許多多 Web 站點都在討論 Google Maps,但是本文主要關注如何結合使用 Google Maps 與 DB2 或 Informix。如果在 Google 上搜索 “google maps api PHP”,會得到超過 3000 萬個結果,而 本系列的第 1 部分 排在前 10 位之內。
應用程序
除了 Terms of Use 中提到的一些限制之外,對於如何使用 Google Maps 應用程序編程接口(API)沒有其他限制。大量站點以不同的方式使用 Google Maps 向各種各樣的用戶顯示不同的信息。這些基於 Google Maps 的頁面被稱為 “mashup”。在本文中,我們將開發一個簡單的 mashup 示例,它使用來自美國人口局的數據。
圖 1. 首先裝載的頁面
圖片看不清楚?請點擊這裡查看原圖(大圖)。
在這個頁面頂部,有一個用於輸入郵政編碼的框。這個框的下面是地圖,右邊顯示相關信息。
圖 2. 郵政編碼 02222 的搜索結果頁面
圖片看不清楚?請點擊這裡查看原圖(大圖)。
在搜索一個郵政編碼時,地圖會以這個郵政編碼的位置為中心放大。它還會創建 “圖釘” 標志來顯示搜索的郵政編碼和這個地區的其他郵政編碼。用星號(*)突出顯示的圖釘表示搜索的郵政編碼。不同顏色的標志表示每個郵政編碼區域的人口密度。
數據
在這個應用程序中,郵政編碼的數據來自美國人口局,美國人口局免費在線提供這些數據和其他地理信息。盡管這是地理數據,但是數據模式很簡單。
清單 1. 應用程序的數據模式Column name Type
state char(2)
zip char(5)
longitude decimal(16)
latitude decimal(16)
population integer
housingunits integer
sqmeters int8
Google Maps API Version 2、JavaScript 和 AJax
Google 的 Maps API 工具集允許任何人創建自己的在線地圖。原來的版本(Version 1)是在幾年前發布的,Version 2 是在 2006 年 4 月 3 日發布的。這個升級版重新設計了 API 的基礎部分,減小了下載包,改進了功能。這個升級版具有 99% 的向後兼容性,但是也有一些不兼容的地方。
為了幫助用戶切換到新版本,Google 提供了一個升級指南並列出兩個版本之間的不兼容之處。下面是一些重點(方法名、常量名等等)。完整的 API Upgrade Guide 可以在網上找到。
縮放級別:在舊的 API 中,縮放級別 0 是視距最近的。現在,它是最遠的。可以按照 newZoom = 17 - oldZoom 轉換縮放級別。
大多數方法名已經簡化了,例如 getZoomLevel() 現在是 getZoom(),getBoundsLatLang() 現在是 getBounds()。
地圖類型名有微小變化。例如,G_HYBRID_TYPE 現在是 G_HYBRID_MAP。
AJax
AJax 代表 “異步 Javascript 和 XML(Asynchronous JavaScript and XML)”。這是 Google Maps 幕後的主要組件之一,控制著應用程序的工作方式。在查看新信息時,大多數動態 Web 站點都要求用戶重新裝載頁面,而 Ajax 允許在不重新裝載頁面的情況下更新頁面上的信息。這就是實現地圖拖放功能的方法 —— 在拖動地圖時,服務器發送用戶請求的地區的圖像,地圖立即裝載它。對於我們的應用程序,使用 AJax 自動地裝載郵政編碼數據,不需要刷新頁面。
DB2 和 Informix
IBM 站點把 DB2 描述為 “一種提供靈活且經濟有效的數據庫平台的數據庫管理系統,可以用來構建健壯的隨需應變業務應用程序”,把 Informix 描述為一種 “為事務密集型環境提供卓越的應用程序性能” 的數據庫。
mashup 使用的主要 DB2 特性是 REC2XML。可以使用這個特性查詢一個常規表並返回經過格式化的 XML(在這裡,使用人口普查數據和模式)。Informix 中的對應特性稱為 genXML,在 代碼示例 小節中提供了這兩個特性的示例。
體系結構概述
圖 3. 體系結構圖
這個圖展示創建和運行應用程序所需的各個組件之間的交互。最初的請求源自浏覽器,用戶在浏覽器中輸入郵政編碼。郵政編碼按照 AJax 方式發送到 apache 服務器,在服務器上用 PHP 和 Open Database Connectivity(ODBC) 創建並執行一個查詢。然後,PHP 用 DB2 或 Informix 返回的數據創建格式化的 XML,用 AJax 接收並用 Javascript 解析這個 XML 文檔。當 JavaScript 得到信息之後,它就可以調用 API 來裝載這個地區的地圖。然後,重復這個過程,使用另一個 PHP 和 AJax 腳本裝載圖釘標志。
在使用 DB2 的 REC2XML 時,這個過程略有不同。因為 PHP 不再需要創建格式化的 XML,只需把它傳輸到客戶端。
PHP 和 ODBC
PHP 是一種常用的 Web 腳本語言。在這個應用程序中,PHP 實際上是一個 “中間人”,它在數據庫和浏覽器之間傳遞數據。ODBC 使 PHP 能夠與數據庫通信。
代碼示例
在這個應用程序中有三個腳本:
用戶看到的頁面,其中包含所有 JavaScript™、AJax 和 API 調用。
調用的第一個 PHP 腳本,它返回與用戶的郵政編碼對應的經度/緯度。
調用的第二個 PHP 腳本,它返回用戶看到的地圖上所有郵政編碼的相關信息。
可以從本文末尾下載這些腳本。下面討論對新的 API 以及 REC2XML(DB2)和 genXML(Informix)最重要的代碼。
清單 2. 更新地圖的代碼var maxZoom=12;// this is the farthest out they can zoom while still seeing markers.
//event listener for movement takes care of refreshing
GEvent.addListener(map, 'moveend', function() {
var center = map.getCenterLatLng();
var latLngStr = "Long/Lat of map center: ";
latLngStr += '(' + Math.round(center.y*10000)/10000 + ', '
+ Math.round(center.x*10000)/10000 + ')';
document.getElementById("longlat").innerHtml = latLngStr;
var zoomstring="Zoom Level: ";
zoomstring +=map.getZoom();
var divZoom = document.getElementById("zoomlev").innerHtml = zoomstring;
if (map.getZoom() >= maxZoom)
getZips();
else
{
document.getElementById("searchstatus").innerHtml = "";
document.getElementById("ziplist").innerHtml = "";
document.getElementById("zipstatus").innerHtml =
"<b>Zoom in closer to see the zip code list</b>";
map.clearOverlays();
}
});
這段代碼定義一個 GEvent.addListener ,它監聽所有地圖運動(拖、放、縮放、搖移、地圖類型切換)並定義相應的操作。代碼的一部分定義是否應該根據地圖的縮放級別更新郵政編碼。因為新的 API 顛倒了放大/縮小的方向,所以修改了所有常量和算式來反映這一點。maxZoom 過去是 6,現在是 12。另外,Zoom 必須大於 maxZoom 而不是小於。
清單 3. DB2 REC2XML 調用示例select
rec2XML(1.0, 'COLATTVAL',' Zip', zip, state, longitude, latitude, population, sqmeters)
from census_data
where longitude > -71.2928581237793 and longitude < -71.1723518371582
and latitude > 42.291532494305976 and latitude < 42.35511892873107
fetch first 200 rows only
這個查詢示例調用 REC2XML 函數。這與常規的選擇查詢非常相似,惟一的差異是使用了 rec2XML() 函數和幾個額外參數。這個調用返回以下輸出:
清單 4. DB2 REC2XML 輸出示例<Zip>
<column name="ZIP">02458</column>
<column name="STATE">MA</column>
<column name="LONGITUDE">-0071.188092</column>
<column name="LATITUDE">0042.354727</column>
<column name="POPULATION">12150</column>
<column name="SQMETERS">4872457</column>
</Zip>
<Zip>
<column name="ZIP">02459</column>
<column name="STATE">MA</column>
<column name="LONGITUDE">-0071.193009</column>
<column name="LATITUDE">0042.321197</column>
<column name="POPULATION">17856</column>
<column name="SQMETERS">12598371</column>
</Zip>
<Zip>
<column name="ZIP">02460</column>
<column name="STATE">MA</column>
<column name="LONGITUDE">-0071.209073</column>
<column name="LATITUDE">0042.352996</column>
<column name="POPULATION">9143</column>
<column name="SQMETERS">3700602</column>
</Zip>
...
在 REC2XML 調用返回的 XML 中只有三個郵政編碼。這個 XML 的格式與我們編寫的 PHP 采用的 XML 格式有點不一樣。另外,其中沒有根元素標記,也沒有在頂部指定 XML version 1.0。因此,PHP 在轉發 XML 之前需要添加這兩項內容。
Informix 函數 genXML 使用一種稍微不同的查詢語法,代碼與第一個實現中使用的 PHP 腳本相似。
清單 5. Informix genXML 查詢示例execute function genXMLquery("Zip",
"select * from census_data where ... ");
這是 genxml 函數的基本語法。但是,與 REC2XML 不同,整個選擇查詢和子句都放在 genxmlquery() 函數中。另外,它返回格式更正確的 XML,其中有一個根結果集標記。
JMeter 速度對比
JMeter 是 apache Jakarta 提供的一種簡潔的工具。對於這個應用程序,可以使用它測試數據庫的速度。在這兩種數據庫的 PHP 腳本上運行數百個請求,然後使用 JMeter 度量返回數據所用的時間。為此,在一個 Thread Group 中添加兩個 HTTP Request 元素並把它們指向 returnMarkers 文件(其中包含相同的經度/緯度變量)。另外,需要添加一個 Listener 元素來制作數據表。
圖 4. JMeter HTTP 請求屏幕
使用一個 Summary Report Listener 並把 Thread Group 設置為每 10 秒 10 個用戶,每個用戶發送 25 個請求。下表給出 Informix 產生的結果:
表 1. JMeter 速度測試產生的數據
數據庫
平均響應時間(ms)
最小(ms)
最大(ms)
KB/sec
Informix
109 ms
15 ms
2031 ms
25.75
Google API Version 2 的其他特性
Google 不僅僅在速度和下載大小方面改進了新的 API,還增加了一些有用的新特性,它們對於某些應用程序很有幫助。新特性包括:
定制的地圖控件:除了 Google 的 Map Controls 之外,現在還可以使用 Googles GControl 類創建定制的控件。
標志管理器:通過新的 API,可以有效地控制其中使用的任何標志。可以根據需要顯示和隱藏標志;在比較高的縮放級別上還可以把標志 “聚合” 起來,從而避免屏幕過分擁擠。
移動方向:這個 API 允許每天最多 10,000 個移動方向請求,這些方向會在它們自己的地圖站點上給出。
更多的縮放級別:這個 API 增加了兩個縮放級別,可以為紐約、波士頓和洛杉矶這樣的地區提供更高的分辨率。
接下來怎麼做?
下面提供了這個應用程序的代碼(DB2 和 Informix)。可以以此作為自己應用程序的起點,也可以根據本文或其他教程從頭創建應用程序。您可以以任意方式使用這個應用程序。
本文示例源代碼或素材下載