nuxt.js 下使用 antv-l7 實在是有太多的坑了,官方文檔也不是很全,只能不斷摸索和嘗試,下面我把這些坑記錄下來,也許能幫到你。
這些解決方案不會是唯一解,也不見得是最優(yōu)解,但至少解決了我的問題,而且還保留了代碼的相對整潔和高效。如果你有更好的解決方案,歡迎留言;如果未來官方修復了這些問題,或者提供了更好的使用方法,那請忽略這篇文章。
nuxt 下只能通過 plugin 的方式引入 l7
不能直接用 import { Scene } from '@antv/l7' 這樣的方法,在任何地方都不行,會出現(xiàn) window undefined 的錯誤
比較隱蔽的情況是,訪問 localhost:3000/ 等頁面是正常的,然后通過點擊菜單(即利用 Nuxt to 來完成跳轉(zhuǎn)),那及時使用了 import 也一切正常,但,這種時候,這個頁面是不能被刷新的,也不能直接訪問,否則一樣會出現(xiàn) window undefined 的錯誤
解決方案就是和其他的 client only 組件一樣,通過 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 中設置為僅 client 引入插件
plugins: [
'@/plugins/fontawesome',
{ src: '@/plugins/g2', ssr: false }, // antv-g2 也是一樣
{ src: '@/plugins/l7', ssr: false },
],
使用時,利用 this.$l7 的方式使用
const { Scene, Popup } = this.$l7
const { GaodeMap, Mapbox } = this.$l7maps
地圖不能重復渲染,會卡死
這個坑出現(xiàn)的原因還沒有找到,懷疑是 antv-l7 這個庫在實現(xiàn)時有問題,也可能是與 nuxt 的某種機制沖突,因為好像單獨用的時候是沒問題的
問題表現(xiàn)如下:假設有一個頁面,叫做 map,其中有 2 個地圖,中國地圖和世界地圖,這兩個地圖顯示在不同的 <div id= 中,利用一個 Switch 按鈕切換
會出現(xiàn)的問題是,首次進入頁面(不妨設進入中國地圖)一切正常,點擊 Switch 切換到世界地圖,正常,再切換回中國地圖,卡死
類似的卡死問題還有,進入 map 頁面后點擊菜單切換到別的頁面,然后切換回來,卡死
使用 antv-l7 提供的 scene.destroy 并不能解決問題
后來利用了 keep-alive 解決,即 <Nuxt keep-alive />,將地圖的代碼封裝成一個 Component,然后把這個組件保留起來,避免重復加載
<Nuxt keep-alive />
圖層的位置在拖動時會變
地圖圖層和標注點的圖層拖動時不一致,導致拖動后點的位置錯位
position: relative
這個其實在官方文檔寫了,這個屬性很重要,否則地圖會鋪滿上層 div,并且縮放時點的位置會偏移
可以根據(jù)自己的情況考慮使用 absolute
MapBox 地圖不會自動鋪滿,而 GaodeMap 會鋪滿
大坑
如果設置了類似于父組件的寬度根據(jù)瀏覽器的寬度變化這樣的功能,期望地圖的大小始終跟著瀏覽器寬度變化的話,GaodeMao 沒有任何問題,會自動鋪滿整個屏幕,但 MapBox 地圖在初次顯示時,仍然會莫名其妙變成 400 * 300 大小,只有在重新改變?yōu)g覽器寬度時才會正確鋪滿
這個問題在 Github 上有人提出(https://github.com/mapbox/mapbox-gl-js/issues/3265),是由于 MapBox 初次加載時長寬一定為 300 * 400,必須經(jīng)過一次 map.resize() 才能正確獲得目標 div 的大小
由于 AntV-l7 做了一層封裝,所以我們不太好直接去調(diào)用 map.resize(),但是我們可以簡單地直接觸發(fā) window 的 resize 事件
scene.on('loaded', () => {
window.dispatchEvent(new Event('resize'))
})
這樣,窗口大小不變,但是 window.resize 被觸發(fā)了,MapBox 的 resize 也被觸發(fā)了,MapBox 的大小也就正常了
地圖的 scene 的 on load 中讀取 vuex 中的值無效
不知道原因,在組件 mounted 的時候去讀 vuex 中的屏幕寬度,期望能夠設置到 div 的樣式,但發(fā)現(xiàn)這個值能夠被正確輸出,地圖大小卻不對
懷疑是 antv-l7 繪制是在 mounted 拿到數(shù)據(jù)之前,但我沒仔細去研究 antv-l7 地圖繪制是在什么階段完成的,所以不知道是不是用 async 這樣的方法就可以確保 mounted 拿到數(shù)據(jù)后才繪制地圖,也可能根本就不是這個原因,總之,我不知道有沒有更好的解決方案
我通過強制讓數(shù)據(jù)發(fā)生變化,觸發(fā) vue 對所有組件的重新繪制
that.screenWidth = that.$store.getters['size/getWidth']
that.screenWidth -= 1
that.screenWidth += 1 // nextTick