:::warning 聚合实现逻辑:在数据源中开启聚合效果,图层通过筛选是否存在point_count值,分别展示不同效果。 :::
一、地图展示效果
二、聚合效果初步实现
1、添加数据源
export const addCluster = async (map,list) => {
let features = []
features = list.map((item) => {
return {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: item.lnglat, // 点位经纬度[lng,lat]
},
properties: item,
}
})
map.addSource(`test_points`, {
type: 'geojson', // geojson类型资源
data: {
/* geojson数据 */
type: 'FeatureCollection',
features: features,
},
cluster: true, // 是否开启聚合
clusterMaxZoom: 15, //最大缩放到聚合
clusterRadius: 100, // 每一组点的半径,默认50
})
}
2、添加图标
export const addImages = async (map) => {
// 注册图标
let icon = require('@/assets/images/icon_ranks_warehouse@2x.png') // 图标地址,可自定义,也可传值
map.loadImage(icon, (err, imgIcon) => {
map.addImage(`test-icon`, imgIcon)
})
}
3、添加图层
export const addLayers = async (map) => {
// 外围有数字的圆圈,加晕染(聚合点)
map.addLayer({
id: 'cluster-point-layer',
type: 'circle',
// minzoom: 12,
source: 'test_points',
filter: ['has', 'point_count'], // 筛选已聚合的点
paint: {
'circle-color': '#ff9969', // 圆圈颜色
'circle-radius': 20, // 圆圈
'circle-stroke-color': 'rgba(255, 153, 105,0.5)',// 光晕颜色
'circle-stroke-width': 7, // 光晕大小,单位px
},
})
// 聚合图圆圈中的数字
map.addLayer({
id: 'cluster-count-layer',
type: 'symbol',
source: 'test_points',
filter: ['has', 'point_count'], // 筛选已聚合的点
layout: {
'text-field': '{point_count_abbreviated}',
'text-size': 11,
},
// 文字样式属性
paint: {
'text-color': '#fff',
'text-opacity': 1,
},
})
// 离散在外部的图标
map.addLayer({
id: `discrete-ponit-layer`,
type: 'symbol',
source: `test_points`,
filter: ['!', ['has', 'point_count']],
layout: {
'text-field': `{label}`,
'text-size': 12,
'icon-image': `test-icon`,
'icon-size': 0.25,
'icon-offset': [0, 0],
'text-offset': [0, 1],
'text-anchor': 'top',
'icon-allow-overlap': true,
'icon-ignore-placement': true,
'text-allow-overlap': true, // 是否允许文本重叠(可选,默认值为 false。当值为 true 时,文本即使和其他符号触碰也会显示)
'text-ignore-placement': false, // 是否忽略文本位置(可选,默认值为 false。当值为 true 时,其他符号即使与此文本触碰也会显示)
'text-optional': false, // 文本是否可不显示(可选,默认值为 false。当值为 true 时,如果文本与图标碰撞,则显示图标)
},
paint: {
'text-color': 'rgba(255,255,255,0)',
},
})
// 聚合图标点击效果,下探一层
map.on('click', 'cluster-point-layer', (e) => {
var features = map.queryRenderedFeatures(e.point, {
layers: ['cluster-point-layer'],
})
var clusterId = features[0].properties.cluster_id
map.getSource('test_points').getClusterExpansionZoom(clusterId, function (err, zoom) {
if (err) return
map.easeTo({
center: features[0].geometry.coordinates,
zoom: zoom,
})
})
})
}
}
三、权重效果添加
方法1,利用step进行范围筛选
(其他代码如二 — addLayers所示)
// 外围有数字的圆圈,加晕染(聚合点)
map.addLayer({
id: 'cluster-point-layer',
type: 'circle',
// minzoom: 12,
source: 'test_points',
filter: ['has', 'point_count'], // 筛选已聚合的点
paint: {
'circle-color': '#ff9969',
'circle-radius': [
'step',
['get', 'point_count'],
20, // 当点数小于100时为20px圆
100, // 筛选条件,点数100以内
21, // 点计数在100到750之间时为21px圆
750, //筛选条件,点数750以内
22, //点计数大于或等于750时为22像素的圆
],
'circle-stroke-color': 'rgba(255, 153, 105,0.5)',
'circle-stroke-width': ['step', ['get', 'point_count'], 5, 100, 6, 750, 7], // 同上'circle-radius'
},
})
方法2:根据mapbox表达式计算
// 外围有数字的圆圈,加晕染(聚合点)
map.addLayer({
id: 'cluster-point-layer',
type: 'circle',
// minzoom: 12,
source: 'test_points',
filter: ['has', 'point_count'], // 筛选已聚合的点
paint: {
'circle-color': '#ff9969',
'circle-radius': ['*', 0.5, ['get', 'point_count']], // point_count值*0.5
'circle-stroke-color': 'rgba(255, 153, 105,0.5)',
'circle-stroke-width': ['*', 0.1, ['get', 'point_count']], // 同上'circle-radius'
},
})
四、其他效果实现
其他代码与二相同,只替换了 addLayers 方法
export const addLayers = async (map,countLength) => {
// countLength为图标总数
// 聚合图标(权重、数字)
map.addLayer({
id: 'cluster-point-layer',
type: 'symbol' /* symbol类型layer,一般用来绘制点*/,
source: `test_points`,
filter: ['has', 'point_count'],
layout: {
'text-field': '{point_count_abbreviated}',
'text-size': 14,
'icon-image': `test-icon`,
'icon-size': ['*', 0.25, ['+', 1, ['/', ['get', 'point_count'], countLength]]],
'text-offset': {
property: 'point_count', // 属性名(填写后 stops 的输入值就是对应的属性值)
stops: [
// 断点(除了 type 为 identity 外必填,由输入值和输出值为一组,作为数组的元素)
[0, [-0.1, -1.5]], // 属性 point_count 的值为 0 时,text-offset 为 [-0.1, -1.5]
[countLength, [-0.1, -2.2]], // 属性 point_count 的值为 countLength 时,text-offset 为 [-0.1, -2.2]
],
}, //property function可以限定最大值最小值,对其中的数值进行平滑插入变化
'icon-allow-overlap': true,
'icon-ignore-placement': true,
'text-allow-overlap': true, // 是否允许文本重叠(可选,默认值为 false。当值为 true 时,文本即使和其他符号触碰也会显示)
'text-ignore-placement': false, // 是否忽略文本位置(可选,默认值为 false。当值为 true 时,其他符号即使与此文本触碰也会显示)
'text-optional': false, // 文本是否可不显示(可选,默认值为 false。当值为 true 时,如果文本与图标碰撞,则显示图标)
},
paint: {
'text-color': 'rgba(255,255,255,1)',
'text-opacity': 1, // 文本的不透明度(可选,取值范围为 0 ~ 1,默认值为 1)
// 'text-color': '#000000', // 文本的颜色(可选,默认值为 #000000)
},
})
// 离散图标
map.addLayer({
id: `discrete-ponit-layer`,
type: 'symbol' /* symbol类型layer,一般用来绘制点*/,
source: `test_points`,
filter: ['!', ['has', 'point_count']],
layout: {
'icon-image': `ss-icon`,
'icon-size': 0.25,
'icon-offset': [0, 0],
'icon-allow-overlap': true,
'icon-ignore-placement': true,
},
})