移動端H5地圖離線瓦片方案


文章版權由作者李曉暉和博客園共有,若轉載請於明顯處標明出處:http://www.cnblogs.com/naaoveGIS/

1.背景

移動端的網速和流量耗費是移動開發必須考慮的兩個點。常規的瓦片展示方案是移動端實時請求在線瓦片服務(瓦片放在服務器端供直接讀取,或者瓦片由地理服務器發布成WMTS服務等)。這個方案存在兩個問題:

* 瓦片實時請求加載受限於移動端網速,容易導致加載卡頓現象

* 瓦片請求耗費手機流量。

試想,如果我們將切圖瓦片提前存放到移動設備上,每次瓦片請求時直接讀取設備緩存瓦片,不僅可以提高瓦片加載效率,也可以規避流量的耗費。目前各大地圖廠商也都提供了地圖下載功能,使得手機即使在無網環境下依然可以照常使用地圖。

2.方案研究點

  • JS無法直接讀取移動端本地文件,如何進行本地瓦片獲取
  • 避免下載全部瓦片導致的數據量過大,如何實現瓦片基於單元網格(最小打包單元,相對穩定,避免使用責任網格打包后由於網格變動導致的重復工作量)的打包,如何基於單元網格瓦片生成責任網格的打包,並實現上傳更新。
  • 瓦片為規則矩形,如何實現在移動端只顯示不規則面(責任網格)內的地圖信息,即裁剪顯示

3.JS讀取手機本地瓦片文件的解決方法

3.1方法描述

  • 與手機研發定義讀取本地瓦片時的固定URL前綴,手機程序監聽所有請求,當匹配上該固定前綴時,則表明手機程序需進行文件讀取,如:
    var offlineURL = "http://mobile.test.com.cn/tile? "
  • 請求參數帶有瓦片級別、行、列、文件名參數。手機程序解析這些參數,讀取本地對應瓦片,並將數據返回

3.2優化

請求參數中增加瓦片服務端獲取URL,當手機本地沒有尋找到對應瓦片時,則觸發服務端獲取的URL,從服務端獲取瓦片后再緩存至手機本地,如:

var offlineURL = "http://mobile.test.com.cn/tile?raw=" url = offlineURL+encodeURIComponent(url)+"&level="+level+ "&row="+row+"&col="+col+"&layername="+(this.get("mobileCacheName")||"");

對在線URL進行編碼(可將URL中的特殊符號轉換),便於手機程序獲取raw參數對應的值。

4.基於網格圖層的瓦片打包工具

4.1工具設計思路

  • 獲取瓦片切圖的具體參數:包含各級別比例尺、切圖原點、瓦片大小
  • 遍歷網格圖層獲取圖層各要素,獲得各要素的四角范圍
  • 通過切圖參數以及要素的四角范圍,算出該范圍所對應的所有瓦片,將這些瓦片保留原有文件組織結構拷貝至目錄文件夾下。遍歷處理所有要素對應的四角范圍瓦片。

  • 將目標文件夾壓縮成一個文件

        

    public static int getXTileIndex(double x,double originx,double resolution,double size) { double d = (x - originx) / (resolution * size); int index = (int)Math.Floor(Math.Abs(d)); return index; } public static int getYTileIndex(double y, double originy, double resolution, double size) { double d = (y - originy) / (resolution * size); int index = (int)Math.Floor(Math.Abs(d)); return index; } public static String calcPath(String dir,int level,int yindex,int xindex) { StringBuilder sb = new StringBuilder(dir).Append("\\").Append("L"); sb.Append(padLeft(Convert.ToString(level, 16), 2, '0')); sb.Append("\\").Append("R").Append(padLeft(Convert.ToString(yindex, 16), 8, '0')); sb.Append("\\").Append("C").Append(padLeft(Convert.ToString(xindex, 16), 8, '0')); sb.Append(".png"); return sb.ToString(); } private static String padLeft(String str, int size, char symbol) { if (str == null) str = ""; int str_size = str.Length; int pad_len = size - str_size; StringBuilder retvalue = new StringBuilder(); for (int i = 0; i < pad_len; i++) { retvalue.Append(symbol); } return retvalue.Append(str).ToString(); }

4.2工具展示

5.手機服務端進行瓦片整合以及上傳

5.1基於單元網格切片合成責任網格切片

單元網格的切片組織如下:

即:網格編碼_alllayers\level\row\col.png
所以,服務端進行責任網格瓦片合並方法如下:

  • 讀取責任網格與單元網格的對應關系表,獲取每個責任網格編碼對應的所有單元網格編碼
  • 在單元網格切片文件夾中找到所有對應的單元網格編碼切片文件夾
  • 以增量覆蓋方式,將各單元網格文件夾中的文件(從_allLayers文件夾至下)進行合並,合並后的文件存放至責任網格編碼的文件夾下
  • 將各責任網格文件分別壓縮

5.2責任網格瓦片打包上傳

服務端修改更新配置,當移動端再次啟動時,依據不同移動端所屬的責任網格區域進行對應的瓦片下載和解壓。

6.成果展示

 

7.前端優化展示效果——遮罩展示

由於瓦片是規則四邊形,而區域是不規則多邊形,所以全圖瀏覽時會出現太多不在區域范圍內的數據。 這里可以使用遮罩的思想進行處理:制作一個很大的四邊形,然后以區邊界要素為內環,兩者結合構成一個環狀要素。疊加在地圖上時,把多邊形環要素設置為背景色,這可以變相實現遮罩效果。

 

                                                                                 -----歡迎轉載,但保留版權,請於明顯處標明出處:http://www.cnblogs.com/naaoveGIS/

                                                                            如果您覺得本文確實幫助了您,可以微信掃一掃,進行小額的打賞和鼓勵,謝謝 ^_^

                                                                                                                           


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM