上一篇關於 ArcIMS 的文章中提到了Mapdex使用ArcIMS和 GMap 的API構建GMap風格的網絡地圖,但需要使用GMap的API,本文則介紹一種無須使用任何API的解決方案。
要構建GMap風格的網絡地圖,首先需要有一個類似GMap風格的JS庫,作爲客戶端;其次是如何使該客戶端和ArcIMS連接起來,如何緩存圖片等等。本文是在以下基礎上構建的:
- MapEasy,一個國人寫的網絡地圖JS庫,可以在mapeasy.sf.net下載,不過該庫好像很久沒有更新了,比較可惜。類似的JS庫還有不少,但沒有相對完整、可用的。
- 來自Maplex的一段連接GMap API和ArcIMS的ASP程序,本文的程序是在這段程序的基礎上修改而來的。
以下是運行截圖:
讀者可以 下載 試用,地址:
http://www.3snews.net/html/95/295_itemid_2823.html
使用前需要修改config.asp文件中的有關參數:
ArcIMSServer = "localhost" ' 服務器 ArcIMSServerHost = 5300 ' 端口 MapService = "BlueViewer" ' 地圖服務 MapImageWidth = 256 ' 輸出地圖的大小 ' 地圖的範圍 MapXMin = -130 MapXMax = -50 MapYMin = 0 MapYMax = 70 ImageType = "png" ' 輸出類型 CacheName = "test" ' 緩存名稱 CacheDir = "E:/Documents/ArcIMS/GMap/img/" ' 緩存路徑 |
然後在瀏覽器中打開瀏覽即可。
需要說明的是,由於客戶端的JS代碼默認的範圍是(-180,180,-90,90),因此,按照經緯度座標加上去的標註返回位置不對,需要進行校正。
下面簡單說一下運行機制:
在html文件中,創建一個地圖的JS代碼:
function IMSMapType() { MapType.apply(this); this.getSrc = function(level, row, column) { return "arcims.asp?z="+level+"&x="+column+"&y="+row } } MapModel.mapTypes = new Array(new IMSMapType()); MapModel.maxZoomLevel=10 |
這段代碼創建了一個地圖類型,也可以創建多種地圖類型(類似GMap),其中getSrc函數定義瞭如何返回圖片的方法,其中有3個參數:縮放比例、橫向位置和縱向位置。而在MapEasy這個庫中,不同縮放級別的圖片是按照類似二維數組的下標方式拼接的。
例如縮放比例爲2(4(22)幅拼接圖片):
0,0 1,0
0,1 1,1
縮放比例爲3(8(23)幅拼接圖片):
0,0 1,0 2,0 3,0
0,1 1,1 2,1 3,1
0,2 1,2 2,2 3,2
0,3 1,3 2,3 3,3
也就是說,從左上角依次增加數值,然後調用arcims.asp,根據位置參數和縮放比例,將地圖縮放到相應的位置(縮放比例),返回圖片就可以了。
在arcims.asp 中,主要的程序流程就是(下圖),首先根據圖片的位置參數,構建圖片名,然後判斷是否存在,如果存在,則返回之,否則調用ArcIMS渲染並保存圖片。其 中返回圖片沒有使用重定向到圖片,而是通過寫數據流的方式來做的(類似ASP中上傳文件保存到數據庫,然後返回給客戶端的做法)。
如果判斷圖片在緩存存在的執行流程爲:1,2,3,7;判斷圖片在緩存不存在的執行流程爲:1,2,4,5,6,7。所以,每個縮放比例的圖片在ArcIMS中只渲染一遍,因此可以大大提高運行效率。
其中如何獲取一幅地圖的代碼如下:
if isObject(Session("IMSGmapMapObj")) then Set mMap = Session("IMSGmapMapObj") else call InitMapServer() end if set mLayers = mMap.Layers '計算地圖範圍,獲得寬度 Dim MapWidth1, MapWidth2 MapWidth1 = MapXMax - MapXMin MapWidth2 = MapYMax - MapYMin If MapWidth1 < MapWidth2 Then MapWidth = MapWidth1 Else MapWidth = MapWidth2 End if Dim mExtent Set mExtent = Server.CreateObject("aims.Envelope") mExtent.XMin = MapWidth / (2^(z-1)) * x + MapXMin mExtent.YMin = MapWidth / (2^(z-1)) * (2^(z-1) - y - 1) + MapYMin mExtent.XMax = mExtent.XMin + MapWidth / (2^(z-1)) mExtent.YMax = mExtent.YMin + MapWidth / (2^(z-1)) mMap.DoZoomToExtent mExtent mMap.Refresh OUT_IMAGEURL = mMap.GetImageAsUrl() |
首先獲得地圖對象(如果沒有緩存在Session,則初始化服務器),然後計算範圍,根據參數返回範圍內的地圖路徑。
地圖保存後,通過Response.BinaryWrite向瀏覽器端發送,這種方式可以保護圖片,例如可以將圖片保存在通過Web服務器無法直接訪問的地方,在返回圖片時進行身份驗證。
ps:
目前對於大多數開發者,最缺乏的是一個可用的、功能齊全的JS前端,MapEasy提供了基礎的功能,如果可以在這基礎上繼續完善,是一件不錯的事情。MapTools下的Kmap也是一個類似的東西,但由於和PHP綁定比較死,要在其他環境使用還需要一些工作。
通過透明圖層疊加,或者在渲染端做一些工作,可以使類似應用增加圖層功能,這樣就可以用於比較專業的領域。