Openlayers(五)点位聚合Cluster
1.业务问题
由于点位在地图上显示过多,会造成页面卡顿、点位标注信息相互叠加导致看不清
优化后效果
不断放大层级
2.聚合类Cluster
OpenLayers 中聚合是通过 ol.source.Cluster
实现,聚合的原理是将距离比较近的点位合并为一个点,并计算合并后点位的属性值。
在聚合源 ol.source.Cluster
中,当一个点被添加进来时,会检查该点与已有聚合点的距离是否在指定的聚合距离之内,如果是,则将该点加入到该聚合点中,同时更新聚合点的属性值(例如点数等)。如果该点与已有聚合点的距离都超出聚合距离,则将该点作为新的聚合点,加入到聚合源中。
在渲染时,对于聚合后的点,可以根据聚合点的属性值设置不同的样式,以区别于普通的点位。
重要参数说明
let clusterPondSource = new Cluster({
distance: 100,
source: new Vector()
});
distance: 聚合的距离,单位是像素
在聚合时,OpenLayers会计算每个点在屏幕上的像素位置,并根据像素位置计算聚合距离。因此,聚合距离不是以地理距离的方式计算的,而是以屏幕上的像素距离为基础。聚合距离的大小取决于地图缩放级别、地图分辨率和聚合距离参数的值。
聚合代码
在原本代码基础上,只需要把VectorLayer中数据源source替换成聚合类Cluster
import Cluster from "ol/source/Cluster"
//加载前端图片地址
const iconTag = reactive({
title: `/public/title.png`,
pond:`/public/pond.svg`
})
let clusterPondSource = new Cluster({
distance: 100,
source: new Vector()
});
let layerPondIcon = new VectorLayer({
id: "layerPondIcon",
title: 'layerPondIcon',
source: clusterPondSource,
zIndex: 1000,
style: function (feature, resolution) {
return clusterStyle(feature,iconTag.pond,'#33C7CCFF')
}
})
聚合样式
其中
let count = feature.get(“features”).length;
获取点位个数,判断当前点位如果数量大于1为聚合点,加载自定义圆。如果只有一个点位,显示我们原本点位。
function clusterStyle(feature,imgSrc,fillColor){
let count = feature.get("features").length;
if (count > 1) {
//聚合样式
return new Style({
image: new Circle({ // 圆形
radius: 15, // 半径
stroke: new Stroke({ // 边框
color: '#fff'
}),
fill: new Fill({ // 填充
color: fillColor
})
}),
text: new Text({
fill: new Fill({
//文本填充样式(即文字颜色)
color: "#ffffff",
}),
font: "bold 14px sans-serif",
text: count > 1 ? count.toString() : feature.get("features")[0].values_.name
}),
});
} else {
//默认样式
return new Style({
image: new Icon({
src: imgSrc,
}),
text: new Text({
textAlign: 'center', //位置
textBaseline: 'middle', //基准线
font: 'normal 13px 微软雅黑', //文字样式
offsetY: -25, // Y轴偏置
text: feature.get("features")[0].values_.name, //文本内容
fill: new Fill({ //文本填充样式(即文字颜色)
color: '#FFF89A'
}),
stroke: new Stroke({
color: '#12a2ee',
width: 2
})
})
});
}
}
Select事件替换
在监听select
事件的回调函数中判断当前选中的是单个点还是聚合点,如果是聚合点位,点击会放大地图层级,如果是单个点位,加载之前业务。
let selectSingleClick = new Select({ style: null });
myMap.value.addInteraction(selectSingleClick);
// feature点击事件
selectSingleClick.on("select", (e) => {
let selectedFeatures = e.selected;
if (selectedFeatures.length > 0) {
let feature = selectedFeatures[0];
let features = feature.get('features');
if (features.length === 1) {
// 单个点位
// 执行之前的业务逻辑
console.log('之前业务')
} else {
// 聚合点
// 放大地图层级
myMap.value.getView().animate({
center: feature.getGeometry().getCoordinates(),
zoom: myMap.value.getView().getZoom() + 1
});
}
}