公司开发一款大屏应用,技术栈是vue3+高德地图,要求加载百万级的标记点,开发过的童鞋都知道,设计海量级标记点开发,必定绕不开聚合点,在过程中也是换了不少方案,最终找到了解决方案,不敢称最优解,但还像是想分享出来,与各位道友共勉,如有分歧,以你为准,下面上代码:
1.申请开发者,获取秘钥,可参照这篇文章,讲的很详细,本文不水了;
2.在根目录的html.index文件加载高德地图相关资源
<script src="https://webapi.amap.com/maps?v=1.4.15&key=你的key值&plugin=AMap.MarkerClusterer"></script>
<script src="https://webapi.amap.com/ui/1.1/main.js?v=1.1.1"></script>
3.创建地图组件AMap.vue
(1)模板部分
<template>
<div id="map"></div>
</template>
(2)js部分
<script setup>
//定义地图对象(划重点:一定、一定、一定不要用ref定义地图相关的对象,否则会报vg、ud等聚合点的错,切记!)
let map = nullconst
const initMap = () => {
map = new AMap.Map('map',{
zoom: 18, //地图放大级别,根据自身需求自行定义
center: [108.366407,22.8177]
})
}map.setMapStyle('amap://styles/darkblue') //地图主题颜色,可参照: 高德地图主题
// 标记点储存对象(划重点:一定、一定、一定不要用ref定义地图相关的对象,否则会报vg、ud等聚合点的错,切记!)
var markerList = []
// 聚合点储存对象(划重点:一定、一定、一定不要用ref定义地图相关的对象,否则会报vg、ud等聚合点的错,切记!)
var cluster = null
// 生成标记点
const initMarkers = (source = []) => {
if(!source.length) return
// 清除之前的标记,不然只会追加不删除没选中的点
clearMarkers()
for (var i = 0; i < source.length; i += 1) {
markerList.push({
new AMap.Marker({
position: source[i]['position'],
content: getIconType(source[i]['type'], color, size),
offset: new AMap.Pixel(-source[i].size / 2, -source[i].size)
})
})
}
// 标注添加点击事件
markerList.forEach((marker, i) => {
marker.on('click', function (e) {
//DOTO
console.log('标注添加点击事件: ', source[i])
})
})
// 清除cluster聚合点实例
cluster && cluster.setMap(null)
var count = markerList.length
var _renderClusterMarker = function (context) {
var div = document.createElement('div')
div.style.width = '50px'
div.style.height = '50px'
div.style.lineHeight = '50px'
div.style.backgroundImage = `url(/static/cluster1.png)` //自定义图标背景
div.style.backgroundSize = '100%'
div.style.backgroundRepeat = 'no-repeat'
div.innerHTML = context.count //聚合个数
div.style.color = '#FFF'
div.style.fontSize = '14px'
div.style.paddingBottom = '10px'
div.style.boxSizing = 'border-box'
div.style.textAlign = 'center'
var size = Math.round(
30 + Math.pow(context.count / markerList.length, 1 / 5) * 20 //markers所有标点对象集合
)
context.marker.setOffset(new AMap.Pixel(-size / 2, -size / 2))
context.marker.setContent(div) }
}
cluster = new AMap.MarkerClusterer(map, markerList, {
gridSize: 50,
renderClusterMarker: _renderClusterMarker
})
}/**
* 返回图标类型
* @param hiddenDangerGrade 隐患级别 0:无隐患 1:一般隐患 2:严重隐患
* @param rectificationState 整改情况 0:未整改 1:部分整改 2:已整改
* @param color 标记点颜色
* @param size 标记点尺寸
*/
const getIconType = (type, color, size = 32) => {
let svg = ''
switch (type) {
case 0:
svg = `<svg fill="${color}" style="width: ${scle(size)}px;height: ${scle(size)}px" t="1734006005662" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2124" width="64" height="64"><path d="M754.38 791.96V359.43c0-106.43-106.42-127.83-106.42-127.83h-29.74V125.17l29.74 0.39s7.83 0.39 7.83-15.65-7.83-14.37-7.83-14.37H376.39s-8.61 2.61-8.61 15.15 7.83 15.65 7.83 15.65h30.13V231.6c-146.35 0-136.04 129.52-136.04 129.52v430.83c0 58.7 37.83 52.96 37.83 52.96l45.39 0.26V913c0 17.36 14.87 15.22 14.87 15.22s272.35 0.15 288.28 0.15c15.93 0 15.11-15.11 15.11-15.11v-68.09h44.44c41.57 0 38.76-53.21 38.76-53.21zM587.57 231.87h-60.52v-38.09h22.7s7.57-0.13 7.57-14.61-7.17-15.26-7.17-15.26h-75.91s-7.43 0.69-7.43 14.28 7.43 15.65 7.43 15.65l22.7 0.2 0.2 37.83H436.1V126.22h151.5v105.65z" p-id="2125"></path></svg>`
break;
case 1:
svg = `<svg fill="${color}" style="width: ${scle(size)}px;height: ${scle(size)}px" t="1734005962340" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1967" width="64" height="64"><path d="M754.38 791.96V359.43c0-106.43-106.42-127.83-106.42-127.83h-29.74V125.17l29.74 0.39s7.83 0.39 7.83-15.65-7.83-14.37-7.83-14.37H376.39s-8.61 2.61-8.61 15.15 7.83 15.65 7.83 15.65h30.13V231.6c-146.35 0-136.04 129.52-136.04 129.52v430.83c0 58.7 37.83 52.96 37.83 52.96l45.39 0.26V913c0 17.36 14.87 15.22 14.87 15.22s272.35 0.15 288.28 0.15c15.93 0 15.11-15.11 15.11-15.11v-68.09h44.44c41.57 0 38.76-53.21 38.76-53.21zM436.07 126.22h151.5v105.65h-60.52v-38.09h22.7s7.57-0.13 7.57-14.61-7.17-15.26-7.17-15.26h-75.91s-7.43 0.69-7.43 14.28 7.43 15.65 7.43 15.65l22.7 0.2 0.2 37.83H436.1V126.22zM506.67 677c-56.54 0-102.07-44.67-102.07-100.14 0-32.76 24.72-48.17 24.33-92.84 34.54 9.63 40.82 36.97 38.47 54.31 24.75-28.49 23.57-60.86 23.57-107.85 78.93 29.29 60.46 113.24 62.82 138.68 19.64-15.8 23.57-53.92 23.57-53.92 20.79 10.4 31.4 38.89 31.4 61.63C608.74 632.33 563.21 677 506.67 677z" p-id="1968"></path></svg>`
break;
})
return svg
}// 清除所有标记点
const clearMarkers = () => {
for (var i = 0; i < markerList.length; i++) {
markerList[i].setMap(null)
}
markerList = []
}
onMounted(() => {
initMarkers(markers)
})</script>
(3)css部分
<style>
#map {
width: 100vw;
height: 100vh;
}
</style>
4.标记点数据markers结构如下,这里仅是示例,可自行按需求修改;
const markers = [
{
id: '1',
type: 0,
size: 32,
color: '#F50',
position: [108.366407,22.8177]
}
]
以上便是本次的分享,希望对你有帮助!