mapboxgl 互聯網地圖糾偏插件(三)

先說結論,結論當然是:大功告成,喜大普奔。看效果圖:

好了,接下來說一下過程

先回顧一下這個系列的 第一篇 第二篇

第一篇是直接改的 mapboxgl 源碼,在源碼裡面對瓦片的位置進行糾偏,遇到的問題是,地圖旋轉時會有錯位,還有瓦片糾偏後螢幕邊緣會有空白。

第二篇是寫了一個 mapboxgl 自定義圖層,遇到的問題是,地圖在大比例尺時,瓦片會瘋狂抖動。

這兩篇文章發出後,有兩位大牛針對上面的問題,給出了建設性的意見。

一位是思否上的網友「undefined」(這個不是bug,是他的名稱),他在看了第一篇文章後,找出了地圖旋轉時瓦片錯位的原因,並給出了解決方法。

按照上面的思路,我重新寫了一個不包含旋轉參數的 pixelMatrix 矩陣後,錯位問題解決。

解決了錯位後,接下來解決螢幕邊緣出現空白的問題。

我的思路是,在計算瓦片的顯示範圍時,對顯示範圍進行偏移,讓程式按偏移的範圍去請求瓦片,這樣後續瓦片糾偏後,就不會出現空白區域了。

在二維地圖中,瓦片顯示的範圍是根據螢幕 4 個角的坐標直接計算的。但 mapboxgl 是三維地圖,三維地圖的顯示範圍是根據相機的參數來計算的,需要判斷相機視椎體和瓦片的相交關係,這裡還沒有整明白。

所以,這個方案就又卡這兒了。

另一位網友是 mapboxgl 技術交流群里的「可樂瓶里泡枸杞」,他指出了第2篇文章中,大比例尺時地圖抖動問題的原因,並給出了解決思路。

上圖的部落格鏈接中詳細說明了地圖抖動的原因,大概意思是:webgl 只支援 float32 精度,而 JS 默認是採用 float64 精度,JS 中的高精度數字向webgl 傳輸時會造成精度損失,這種損失帶來的影響就是地圖抖動,比例尺越大抖動的越厲害。

如何能避免精度的損失?部落格中介紹了 deck.gl 的做法:

  1. 將經緯度坐標轉墨卡托坐標這一步,放到 webgl 中來實現,目的是為了使用 GPU 計算
  2. 在比例尺大於12級時,不再直接使用墨卡托坐標,而是計算墨卡托坐標和螢幕中心點的相對位置。使用 float32 的精度保存相對位置是完全沒有問題的,這樣就規避了精度損失的問題
  3. 重寫 view 和 Projection 矩陣

按這個思路,我將上次寫的 mapboxgl 自定義圖層糾偏插件進行了改造,最終大比例尺時地圖不再抖動了。

但又很快遇到了新問題:拖動地圖時,瓦片和滑鼠的移動距離不一致。

返回去看那篇部落格的在線示例,也有同樣的問題

既然這樣,那就解決問題吧,瞅了瞅程式碼,總覺得下面這兩行不順眼,

不除 2 了試試,哈哈,一招命中,問題解決。

至此,mapboxgl 對高德地圖瓦片糾偏的問題成功解決,我把他封裝成了插件,方便大家使用。GIS兵器庫中又多了一件趁手的兵器。

這個插件目前不僅僅是支援高德地圖瓦片,所有 gcj02 坐標的地圖瓦片都支援。

當然,作為插件來講,它還不夠完美,目前發現有這麼幾個可以完善的地方:

  1. 跟 mapboxgl 自帶的瓦片圖層相比,瓦片在縮放時有點發虛
  2. 地圖縮放時,瓦片沒有過渡效果
  3. 移除圖層後,有時會莫名其妙的突然出現
  4. 在手機端顯示有問題

這些問題,後續會慢慢完善。也歡迎大家一起參與進來,多提 Issues 和 Pull requests

地址

在線示例://gisarmory.xyz/blog/index.html?demo=mapboxglMapCorrection3

插件地址://gisarmory.xyz/blog/index.html?source=mapboxglMapCorrection3

總結

  1. 解決 mapboxgl 中高德地圖瓦片偏移的問題有兩個方案,方案一改源碼,方案二寫自定義圖層
  2. 方案一有了突破,解決了地圖旋轉時瓦片錯位的問題,但偏移後螢幕邊緣空白的問題沒有解決
  3. 方案二在成功解決了地圖大比例尺上瓦片抖動的問題後,最終實現了瓦片的糾偏
  4. 將方案二的程式碼封裝成了插件,方便大家使用


原文地址://gisarmory.xyz/blog/index.html?blog=mapboxglMapCorrection3

關注《GIS兵器庫》, 只給你網上搜不到的GIS知識技能。

本文章採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名《GIS兵器庫》(包含鏈接:  //gisarmory.xyz/blog/),不得用於商業目的,基於本文修改後的作品務必以相同的許可發布。