先說結論,結論當然是:大功告成,喜大普奔。看效果圖:
好了,接下來說一下過程
第一篇是直接改的 mapboxgl 原始碼,在原始碼裡面對瓦片的位置進行糾偏,遇到的問題是,地圖旋轉時會有錯位,還有瓦片糾偏後螢幕邊緣會有空白。
第二篇是寫了一個 mapboxgl 自定義圖層,遇到的問題是,地圖在大比例尺時,瓦片會瘋狂抖動。
這兩篇文章發出後,有兩位大牛針對上面的問題,給出了建設性的意見。
一位是思否上的網友“undefined”(這個不是bug,是他的名稱),他在看了第一篇文章後,找出了地圖旋轉時瓦片錯位的原因,並給出瞭解決方法。
按照上面的思路,我重新寫了一個不包含旋轉引數的 pixelMatrix 矩陣後,錯位問題解決。
解決了錯位後,接下來解決螢幕邊緣出現空白的問題。
我的思路是,在計算瓦片的顯示範圍時,對顯示範圍進行偏移,讓程式按偏移的範圍去請求瓦片,這樣後續瓦片糾偏後,就不會出現空白區域了。
在二維地圖中,瓦片顯示的範圍是根據螢幕 4 個角的座標直接計算的。但 mapboxgl 是三維地圖,三維地圖的顯示範圍是根據相機的引數來計算的,需要判斷相機視椎體和瓦片的相交關係,這裡還沒有整明白。
所以,這個方案就又卡這兒了。
另一位網友是 mapboxgl 技術交流群裡的“可樂瓶裡泡枸杞”,他指出了第2篇文章中,大比例尺時地圖抖動問題的原因,並給出瞭解決思路。
上圖的部落格連結中詳細說明了地圖抖動的原因,大概意思是:webgl 只支援 float32 精度,而 JS 預設是採用 float64 精度,JS 中的高精度數字向webgl 傳輸時會造成精度損失,這種損失帶來的影響就是地圖抖動,比例尺越大抖動的越厲害。
如何能避免精度的損失?部落格中介紹了 deck.gl 的做法:
- 將經緯度座標轉墨卡託座標這一步,放到 webgl 中來實現,目的是為了使用 GPU 計算
- 在比例尺大於12級時,不再直接使用墨卡託座標,而是計算墨卡託座標和螢幕中心點的相對位置。使用 float32 的精度儲存相對位置是完全沒有問題的,這樣就規避了精度損失的問題
- 重寫 view 和 Projection 矩陣
按這個思路,我將上次寫的 mapboxgl 自定義圖層糾偏外掛進行了改造,最終大比例尺時地圖不再抖動了。
但又很快遇到了新問題:拖動地圖時,瓦片和滑鼠的移動距離不一致。
返回去看那篇部落格的線上示例,也有同樣的問題
既然這樣,那就解決問題吧,瞅了瞅程式碼,總覺得下面這兩行不順眼,
不除 2 了試試,哈哈,一招命中,問題解決。
至此,mapboxgl 對高德地圖瓦片糾偏的問題成功解決,我把他封裝成了外掛,方便大家使用。GIS兵器庫中又多了一件趁手的兵器。
這個外掛目前不僅僅是支援高德地圖瓦片,所有 gcj02 座標的地圖瓦片都支援。
當然,作為外掛來講,它還不夠完美,目前發現有這麼幾個可以完善的地方:
- 跟 mapboxgl 自帶的瓦片圖層相比,瓦片在縮放時有點發虛
- 地圖縮放時,瓦片沒有過渡效果
- 移除圖層後,有時會莫名其妙的突然出現
- 在手機端顯示有問題
這些問題,後續會慢慢完善。也歡迎大家一起參與進來,多提 Issues 和 Pull requests
地址
線上示例:http://gisarmory.xyz/blog/index.html?demo=mapboxglMapCorrection3
外掛地址:http://gisarmory.xyz/blog/index.html?source=mapboxglMapCorrection3
總結
- 解決 mapboxgl 中高德地圖瓦片偏移的問題有兩個方案,方案一改原始碼,方案二寫自定義圖層
- 方案一有了突破,解決了地圖旋轉時瓦片錯位的問題,但偏移後螢幕邊緣空白的問題沒有解決
- 方案二在成功解決了地圖大比例尺上瓦片抖動的問題後,最終實現了瓦片的糾偏
- 將方案二的程式碼封裝成了外掛,方便大家使用
原文地址:http://gisarmory.xyz/blog/index.html?blog=mapboxglMapCorrection3
關注《GIS兵器庫》, 只給你網上搜不到的GIS知識技能。
本文章採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名《GIS兵器庫》(包含連結: http://gisarmory.xyz/blog/),不得用於商業目的,基於本文修改後的作品務必以相同的許可釋出。