cesium 切換瓦片地圖的加載方式

cesium 切換瓦片地圖的加載方式

如果你熟悉 cesium,那么你或多或少應(yīng)該用過或者了解如何用 cesium 加載瓦片地圖。

熟悉加載瓦片地圖這本身不是一個太難的工作,一般來說,只要你照著官方的沙盒中的示例,一般都能輕松掌握。

但是問題是,只要你細(xì)心研究過,你就會發(fā)現(xiàn),cesium 加載瓦片地圖,居然是用 ajax 請求的方式來加載貼圖的。

image.png

這種加載方式的優(yōu)劣我們姑且不論,cesium 選擇這種方式必然會有其意義所在。

但是問題是,為什么翻遍 api 和源碼,都沒有找到一個方式,可以更換貼圖的加載方式呢?

我們知道,對于現(xiàn)代的瀏覽器來說,一般都會對傳統(tǒng)的加載圖片做一些優(yōu)化。

比如會進(jìn)行緩存,同樣的圖片,不會重復(fù)向服務(wù)器請求等等。

這兩種加載圖片的方式,用在瀏覽器上,到底哪一種比較比較好,還有待商榷。

截止到目前為止,我還并未找到對兩種加載方式的優(yōu)劣進(jìn)行比較的分析資料。

如果有童鞋曾經(jīng)看過相關(guān)比較好的資料,還希望能積極分享出來。

如果要采用 JavaScript 的方式來加載圖片,該怎么做呢?

一般我們會采用下面的方式:

const img = new Image()
img.src = imgUrl
img.crossOrigin = 'Anonymous'

// 圖片加載成功
img.onload = () => {
  console.log(imgUrl + " 圖片加載成功!")
}

// 圖片加載失敗
img.onerror = () => {
  console.error('圖片:【' + imgUrl + '】加載失敗!')
}

現(xiàn)在問題是,我們怎么將上面這套機(jī)制,應(yīng)用在 cesium 里面呢?

也就是說,我們需要做一些修改源碼的操作。

但是修改源碼最關(guān)鍵的一個要素是,我們只是朝源碼上加功能,而不能對現(xiàn)有的功能造成哪怕一絲絲的影響。

否則,在我們沒有全盤掌握某段代碼的作用的時候,隨意的修改,會造成難以預(yù)料的后果。

對于 JavaScript 來說,有些時候,做到這一點(diǎn),還蠻容易的。

如果源碼是采用面向?qū)ο蟮姆绞綄懙模敲次覀儗υ玩溕夏硞€方法重載下,就能達(dá)到我們想要的效果。

接下倆,我們需要做的就是,找到合適的重載的地方。

那么該如何找呢?

別著急,接下來,我會手把手的教你,該如何找到合適的重載的地方。

首先,我們需要用到我們的好伙伴——chrome devtool。

image.png

當(dāng)然如果你用火狐瀏覽器的開發(fā)者工具,也能達(dá)到同樣的效果,這里就不一一舉例了,直接以 chrome 為例進(jìn)行說明。

我們找到 Network 這一列,刷新下頁面,能看到我們頁面發(fā)的所有的請求。

而 XHR 這一欄里面,就是我們前端頁面所有的 ajax 請求的集合欄了。

隨便點(diǎn)開一個加載瓦片圖的鏈接,你便會詳細(xì)的了解到每個請求的調(diào)用棧。

如何找到合適的地方,進(jìn)行重載呢?

這里貌似沒有什么好方法,只有從上到下,依次將源碼點(diǎn)開研究一番。

最后你會發(fā)現(xiàn),在這個地方進(jìn)行重載,可以達(dá)到比較滿意的效果。

image.png

之所以這么說,原因有幾點(diǎn),這個 loadImage 方法是個靜態(tài)的方法,需要 imageryProvider 的實(shí)例以及圖片的 url 地址,其返回的結(jié)果是個一 Promise,而 Promise 最終返回的值為圖片元素。

既然這個地方用的是 fetchImage 方法,也就是通過 ajax 的方式來獲取圖片的,那么我們直接給這個地方改成傳統(tǒng)的拿圖方式就好了。

import {
  ImageryProvider
} from 'Cesium'

// 將原來的 loadImage 方法重命名
ImageryProvider.loadImage2 = ImageryProvider.loadImage

// 將 loadImage 重載
ImageryProvider.loadImage = function(imageryProvider, url) {
  // 在某些情況下,走我們原來的邏輯
  if(url === some case){
    return ImageryProvider.loadImage2.call(this, imageryProvider, url)
  }
  // 其余情況,采用傳統(tǒng)的加載圖片的方式
  return new Promise((resolve, reject) => {
    const imgUrl = url.url
    const img = new Image()
    img.src = imgUrl
    img.crossOrigin = 'Anonymous'
    // 圖片加載成功了,進(jìn)行 reslove
    img.onload = () => {
      resolve(img)
    }
    // 圖片未加載成功
    img.onerror = (err) => {
      console.error('圖片:【' + imgUrl + '】加載失??!')
      reject(err)
    }
  })
}

如果后面需要進(jìn)一步優(yōu)化的話,為了防止圖片出錯,加載失敗,可以用一個通用的圖片去代替出錯的圖片,以達(dá)到讓程序能夠正常的運(yùn)行的目的。

比如這樣做:

// 圖片未加載成功
img.onerror = (err) => {
  console.error('圖片:【' + imgUrl + '】加載失敗!')
  resolve(ErrorImage)
}

或者這樣做:

// 圖片未加載成功
img.onerror = (err) => {
  console.error('圖片:【' + imgUrl + '】加載失敗!')
  img.url = errorImageUrl
}

總之,在平時寫代碼的過程中,總會有很多小細(xì)節(jié),很值得我們?nèi)?yōu)化,如果優(yōu)化的好,也可以極大的提升用戶的使用體驗(yàn)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容