目录
- 1.业务需求
- 2.最初实现及出现的问题
- 3.解决 - `1000` 个标点时页面就出现 `卡顿` 问题
- 4.使用海量点、聚合标点后还有卡顿,排查其他原因
- 5.最终解决
- 5.1页面中list数据渲染问题解决
- 5.2地图相关实例不要放在 vue 的可响应数据中
- 页面展示
1.业务需求
需要在
高德地图
中标点,标点数量可能上万个
2.最初实现及出现的问题
- 【最初实现】使用高德地图的
Marker
标点Marker 实现标点代码
// 遍历list数据一个一个标点 let warnning = new AMap.Marker({zIndex: type === 'alarm' ? 14 : 12,icon: icon,position: [item.longitude, item.latitude],anchor: 'bottom-center',extData: {tabType: type,...item} }) this.markerList.push(warnning) // 用于 warnning.on('click', this.markerClick) // warnning.emit('click', { target: warnning });// map.add(warnning)
- 【问题】
1000
个标点时页面就出现卡顿
3.解决 - 1000
个标点时页面就出现 卡顿
问题
想尽各种办法:
- 【海量点第一种方法】:
海量点 MassMarks
官方示例 (代码示例如下)- 【海量点第二种方法】:
标注和标注图层-海量点
官方示例- 【点聚合】:
MarkerCluster
官方示例
【海量点第一种方法】代码
<script>
/* 注释掉的代码与当前功能无关 */
let map = null
// let infoWindowCon = null
// let contextMenu = null
let makerPeak = nullexport default {name: 'mapManager',data() {return {// ...dangerSucMass: null // 【关键代码】海量点图层}},methods: {// 使用【海量点第一种方法】实现标点completeAddMarker(data) {this.dangerSucMass?.clear()const list = (data || []).map((item, index) => {return {id: item.id,name: item.address,lnglat: [item.longitude, item.latitude],style: 0,extData: {tabType: 'dangerSuceess',...item}}})this.dangerSucMass = new AMap.MassMarks(list, {opacity: 0.8,zIndex: 111,cursor: 'pointer',style: [{url: require('@/assets/image/green.png'),anchor: AMap.Pixel(0, 0),size: new AMap.Size(10, 10),zIndex: 3}]})this.dangerSucMass.setMap(map)this.dangerSucMass.on('click', this.successMarkerClick)},// 展示/隐藏图标isShowSucMass(e) {if (e) {this.dangerSucMass.show()this.markerTip.open(map)} else {this.dangerSucMass.hide()this.markerTip.close()}},//监听successMarkerClick(e) {console.log('e--successMarkerClick--打印', e)// 添加点击marker时的提示if (this.markerTip) {this.markerTip.close() // 关闭提示}const data = e.data.extDataconsole.log('e.data.extData----打印', data)this.infoWindowData = { ...data, type: 'dangerSuceess' }const position = [data.longitude, data.latitude]map.setCenter(new AMap.LngLat(position[0], position[1]), true)this.markerTip = new AMap.InfoWindow({ // 提示插件position: new AMap.LngLat(position[0], position[1]), // 经纬度content: this.$refs['infoW'].$el,offset: new AMap.Pixel(5, 0) // 偏移位置})this.markerTip.open(map)// this.$refs.infoW.open({...e.data.extData, typeTab: 'dangerSuceess'})},}
}
</script>
4.使用海量点、聚合标点后还有卡顿,排查其他原因
以上三种办法 - 页面还是卡顿 - 基于以上三种解决办法排查到以下多方面原因:
- 页面中有list数据
列表渲染
,数据过多,页面数据渲染过多也会导致页面卡顿
地图相关的变量
在data 中声明
(此处以【海量点第一种方法】为例)
- 以上
【海量点第一种方法】代码
中可以看到,海量点实例dangerSucMass
在data
中声明 ↓↓↓- 所有
地图相关的实例不要放在 vue 的可响应数据中
,响应数据会劫持属性
,地图的属性会被修改
,另外,劫持的属性可能和渲染有关
,那么会增加很多响应的计算
,会很卡; 参考别人遇到的类似的问题-官方解释
5.最终解决
5.1页面中list数据渲染问题解决
最初地图标点和list数据使用的是一套数据
【解决】
地图标点数据
、页面渲染数据
分成两套列表数据
- 地图标点数据:获取所有标点数据
- 页面渲染数据列表:改成分页获取数据,单次获取一部分数据
5.2地图相关实例不要放在 vue 的可响应数据中
最终解决办法【海量点第一种方法】代码
<script>
/* 注释掉的代码与当前功能无关 */
let map = null
// let infoWindowCon = null
// let contextMenu = null
let makerPeak = null
let dangerSucMass = null // 【关键代码】【解决代码】海量点实例 - 不在 data 中export default {name: 'mapManager',data() {return {// ...// dangerSucMass: null // 【关键代码】海量点实例}},methods: {// 使用【海量点第一种方法】实现标点completeAddMarker(data) {dangerSucMass?.clear()const list = (data || []).map((item, index) => {return {id: item.id,name: item.address,lnglat: [item.longitude, item.latitude],style: 0,extData: {tabType: 'dangerSuceess',...item}}})dangerSucMass = new AMap.MassMarks(list, {opacity: 0.8,zIndex: 111,cursor: 'pointer',style: [{url: require('@/assets/image/green.png'),anchor: AMap.Pixel(0, 0),size: new AMap.Size(10, 10),zIndex: 3}]})dangerSucMass.setMap(map)dangerSucMass.on('click', this.successMarkerClick)},// 展示/隐藏图标isShowSucMass(e) {if (e) {dangerSucMass.show()this.markerTip.open(map)} else {dangerSucMass.hide()this.markerTip.close()}},//监听successMarkerClick(e) {console.log('e--successMarkerClick--打印', e)// 添加点击marker时的提示if (this.markerTip) {this.markerTip.close() // 关闭提示}const data = e.data.extDataconsole.log('e.data.extData----打印', data)this.infoWindowData = { ...data, type: 'dangerSuceess' }const position = [data.longitude, data.latitude]map.setCenter(new AMap.LngLat(position[0], position[1]), true)this.markerTip = new AMap.InfoWindow({ // 提示插件position: new AMap.LngLat(position[0], position[1]), // 经纬度content: this.$refs['infoW'].$el,offset: new AMap.Pixel(5, 0) // 偏移位置})this.markerTip.open(map)// this.$refs.infoW.open({...e.data.extData, typeTab: 'dangerSuceess'})},}
}
</script>