nuxt.js 下使用 antv-l7 實(shí)在是有太多的坑了蔗喂,官方文檔也不是很全,只能不斷摸索和嘗試高帖,下面我把這些坑記錄下來(lái)缰儿,也許能幫到你。
這些解決方案不會(huì)是唯一解散址,也不見(jiàn)得是最優(yōu)解乖阵,但至少解決了我的問(wèn)題,而且還保留了代碼的相對(duì)整潔和高效预麸。如果你有更好的解決方案瞪浸,歡迎留言;如果未來(lái)官方修復(fù)了這些問(wèn)題吏祸,或者提供了更好的使用方法对蒲,那請(qǐng)忽略這篇文章。
nuxt 下只能通過(guò) plugin 的方式引入 l7
不能直接用 import { Scene } from '@antv/l7'
這樣的方法,在任何地方都不行蹈矮,會(huì)出現(xiàn) window undefined 的錯(cuò)誤
比較隱蔽的情況是砰逻,訪問(wèn) localhost:3000/
等頁(yè)面是正常的,然后通過(guò)點(diǎn)擊菜單(即利用 Nuxt to
來(lái)完成跳轉(zhuǎn))泛鸟,那及時(shí)使用了 import
也一切正常蝠咆,但,這種時(shí)候北滥,這個(gè)頁(yè)面是不能被刷新的刚操,也不能直接訪問(wèn),否則一樣會(huì)出現(xiàn) window undefined 的錯(cuò)誤
解決方案就是和其他的 client only 組件一樣碑韵,通過(guò) plugin 的方式引入
在 plugins
目錄下新建 l7.js
import Vue from 'vue'
const l7 = require('@antv/l7')
const l7maps = require('@antv/l7-maps')
Vue.prototype.$l7 = l7
Vue.prototype.$l7maps = l7maps
并在 nuxt.config
中設(shè)置為僅 client 引入插件
plugins: [
'@/plugins/fontawesome',
{ src: '@/plugins/g2', ssr: false }, // antv-g2 也是一樣
{ src: '@/plugins/l7', ssr: false },
],
使用時(shí)赡茸,利用 this.$l7
的方式使用
const { Scene, Popup } = this.$l7
const { GaodeMap, Mapbox } = this.$l7maps
地圖不能重復(fù)渲染缎脾,會(huì)卡死
這個(gè)坑出現(xiàn)的原因還沒(méi)有找到祝闻,懷疑是 antv-l7 這個(gè)庫(kù)在實(shí)現(xiàn)時(shí)有問(wèn)題,也可能是與 nuxt 的某種機(jī)制沖突遗菠,因?yàn)楹孟駟为?dú)用的時(shí)候是沒(méi)問(wèn)題的
問(wèn)題表現(xiàn)如下:假設(shè)有一個(gè)頁(yè)面联喘,叫做 map
,其中有 2 個(gè)地圖辙纬,中國(guó)地圖和世界地圖豁遭,這兩個(gè)地圖顯示在不同的 <div id=
中,利用一個(gè) Switch 按鈕切換
會(huì)出現(xiàn)的問(wèn)題是贺拣,首次進(jìn)入頁(yè)面(不妨設(shè)進(jìn)入中國(guó)地圖)一切正常蓖谢,點(diǎn)擊 Switch 切換到世界地圖,正常譬涡,再切換回中國(guó)地圖闪幽,卡死
類似的卡死問(wèn)題還有,進(jìn)入 map
頁(yè)面后點(diǎn)擊菜單切換到別的頁(yè)面涡匀,然后切換回來(lái)盯腌,卡死
使用 antv-l7 提供的 scene.destroy
并不能解決問(wèn)題
后來(lái)利用了 keep-alive
解決,即 <Nuxt keep-alive />
陨瘩,將地圖的代碼封裝成一個(gè) Component腕够,然后把這個(gè)組件保留起來(lái),避免重復(fù)加載
<Nuxt keep-alive />
圖層的位置在拖動(dòng)時(shí)會(huì)變
地圖圖層和標(biāo)注點(diǎn)的圖層拖動(dòng)時(shí)不一致舌劳,導(dǎo)致拖動(dòng)后點(diǎn)的位置錯(cuò)位
position: relative
這個(gè)其實(shí)在官方文檔寫(xiě)了帚湘,這個(gè)屬性很重要,否則地圖會(huì)鋪滿上層 div甚淡,并且縮放時(shí)點(diǎn)的位置會(huì)偏移
可以根據(jù)自己的情況考慮使用 absolute
MapBox 地圖不會(huì)自動(dòng)鋪滿大诸,而 GaodeMap 會(huì)鋪滿
大坑
如果設(shè)置了類似于父組件的寬度根據(jù)瀏覽器的寬度變化這樣的功能,期望地圖的大小始終跟著瀏覽器寬度變化的話,GaodeMao 沒(méi)有任何問(wèn)題底挫,會(huì)自動(dòng)鋪滿整個(gè)屏幕恒傻,但 MapBox 地圖在初次顯示時(shí),仍然會(huì)莫名其妙變成 400 * 300 大小建邓,只有在重新改變?yōu)g覽器寬度時(shí)才會(huì)正確鋪滿
這個(gè)問(wèn)題在 Github 上有人提出(https://github.com/mapbox/mapbox-gl-js/issues/3265)盈厘,是由于 MapBox 初次加載時(shí)長(zhǎng)寬一定為 300 * 400,必須經(jīng)過(guò)一次 map.resize()
才能正確獲得目標(biāo) div
的大小
由于 AntV-l7 做了一層封裝官边,所以我們不太好直接去調(diào)用 map.resize()
沸手,但是我們可以簡(jiǎn)單地直接觸發(fā) window 的 resize 事件
scene.on('loaded', () => {
window.dispatchEvent(new Event('resize'))
})
這樣,窗口大小不變注簿,但是 window.resize 被觸發(fā)了契吉,MapBox 的 resize 也被觸發(fā)了,MapBox 的大小也就正常了
地圖的 scene 的 on load 中讀取 vuex 中的值無(wú)效
不知道原因诡渴,在組件 mounted 的時(shí)候去讀 vuex 中的屏幕寬度捐晶,期望能夠設(shè)置到 div 的樣式,但發(fā)現(xiàn)這個(gè)值能夠被正確輸出妄辩,地圖大小卻不對(duì)
懷疑是 antv-l7 繪制是在 mounted 拿到數(shù)據(jù)之前惑灵,但我沒(méi)仔細(xì)去研究 antv-l7 地圖繪制是在什么階段完成的,所以不知道是不是用 async 這樣的方法就可以確保 mounted 拿到數(shù)據(jù)后才繪制地圖眼耀,也可能根本就不是這個(gè)原因英支,總之,我不知道有沒(méi)有更好的解決方案
我通過(guò)強(qiáng)制讓數(shù)據(jù)發(fā)生變化哮伟,觸發(fā) vue 對(duì)所有組件的重新繪制
that.screenWidth = that.$store.getters['size/getWidth']
that.screenWidth -= 1
that.screenWidth += 1 // nextTick