這里重點討論OpenLayers的網絡瓦片地圖的繪制過程,這里以XYZ圖層作為樣例來調試學習。
比率(ratio):地圖分辨率與對應等級瓦片分辨率的比例。
調試代碼,查看Layer繪圖機制,如下圖:
上圖是簡化的繪制出地圖地圖的整個過程。
(1)任何地圖視圖發生變化的時候都會執行map的moveTo方法,該方法中首先判斷baseLayer是否存在,如果存在,則執行baseLayer的moveTo方法。
(2)在baseLayer的moveTo方法中首先會計算需要繪制的瓦片的行列號(即圖中的initGridTiles),目的是為了計算該瓦片在服務器中的存放地址(url)。
計算瓦片的行列號,需要5個參數:待求瓦片的范圍tileBound,地圖切圖的原點tileOrigin,地圖的分辨率resolution,瓦片的大小tileSize,地圖的切圖方向。
這里假設地圖切圖的方向是從左到右,從上到下,則瓦片行列號的計算方法如下:
colNum = Math.Ceil((tileBound.getCenter().lon - tileOrigin.lon)/(tileSize.width*resolution));
rowNum =Math.Ceil((tileOrigin.lat - tileBound.getCenter().lat )/(tileSize.height*resolution));
(3)在initGridTiles()方法中,除了計算每一張瓦片的行列號之外還計算該瓦片在地圖頁面上的繪圖位置(控件坐標系),目的是為了地圖顯示在前臺頁面上。
計算繪圖位置的方法是,首先取到該圖層在地圖上左上角的地理坐標:
圖中黑色的邊框矩形代表繪圖的屏幕,即map對應的div,紅色邊框的矩形代表瓦片數據,getViewPortPxFromLonLat()方法計算的是某一個地圖坐標的值對應在map的div參考坐標系下的屏幕坐標值。即要計算每一個瓦片繪制在什么位置上,通過該步驟計算得到,此處只要統一計算容器的左上角瓦片的坐標參考(圖中藍色的點),其他的瓦片繪圖位置可以根據該位置推算得到。
在initGridTiles得到一個tileData數組,包含了屏幕上需要顯示的瓦片所需要的所有數據,瓦片的行列號,瓦片的地理范圍坐標,瓦片的屏幕坐標。
(4)完成初始化tileData數組之后,可以開始繪圖,繪圖是調用的renderTile()方法,該方法中可以調用到Layer的getUrl()方法獲取到瓦片數據所在的路徑,然后初始化地圖容器中的該瓦片所對應的div,并在該div中添加img數據,將img的SRC指向瓦片的url,完成地圖的渲染。
結論:
瓦片地圖數據的繪圖方式都是一樣,初始化一個需要繪制瓦片大小一樣的DIV容器,容器中存放一個Img,Img的Src設置為tile的Url。
瓦片地圖數據最關鍵的是計算瓦片所在的服務器路徑,即重寫好getURL方法。
計算瓦片的方法都是一樣,根據切圖原點、瓦片大小、瓦片編號方式就可以計算出某一個瓦片的行列號,關鍵是理解所調用TMS服務的切圖協議。