贴个群号
WebGIS学习交流群461555818,欢迎大家
效果图
有的时候我们会有这样的需求,就是在一坨要素里面,我们想要展示一个重点关注的要素,比如说是温度站点的话,我们要在地图上很明显的看到温度最高的那个站点,如果是降雨站点的话,我们要在地图上看到降雨最高的站点,随之而来就会产生这样的需求。 很合理的需求。
原理和源码
首先建议大家去看看我这篇博客,这个是在要素重叠的时候,如何让叠在一起的要素里面,只展示某个字段值最大或者最下的办法,要不然你即使实现了这个功能,但是这个点位存在要素重叠,但是重点标识的脉冲效果已经出来了,很自然的就以为这个点就是那个重点的点,然后一点开气泡或者弹窗,发现不是,那就太尴尬了,所以我们一定要要素重叠的时候,将重点的点首先要放在最上面。
https://blog.csdn.net/Sakura1998gis/article/details/136505302?spm=1001.2014.3001.5502
然后我们再考虑如何实现这个脉冲点。
首先我们地图初始化的时候,就要先加载好这个脉冲点图层,数据源采用geojson,但是这个时候是空的geojson,里面不要放什么数据
const pulsingDotRed = {
width: sizeRed,
height: sizeRed,
data: new Uint8Array(sizeRed * sizeRed * 4),
// When the layer is added to the map,
// get the rendering context for the map canvas.
onAdd: function () {
const canvas = document.createElement('canvas');
canvas.width = this.width;
canvas.height = this.height;
this.context = canvas.getContext('2d');
},
// Call once before every frame where the icon will be used.
render: function () {
const duration = 1000;
const t = (performance.now() % duration) / duration;
const radius = (sizeRed / 2) * 0.3;
const outerRadius = (sizeRed / 2) * 0.7 * t + radius;
const context = this.context;
// Draw the outer circle.
context.clearRect(0, 0, this.width, this.height);
context.beginPath();
context.arc(
this.width / 2,
this.height / 2,
outerRadius,
0,
Math.PI * 2
);
context.fillStyle = `rgba(255, 200, 200, ${1 - t})`;
context.fill();
// Draw the inner circle.
context.beginPath();
context.arc(
this.width / 2,
this.height / 2,
radius,
0,
Math.PI * 2
);
// context.fillStyle = 'rgba(255, 100, 100, 1)';
context.strokeStyle = 'white';
context.lineWidth = 2 + 4 * (1 - t);
context.fill();
context.stroke();
// Update this image's data with data from the canvas.
this.data = context.getImageData(
0,
0,
this.width,
this.height
).data;
// Continuously repaint the map, resulting
// in the smooth animation of the dot.
map.triggerRepaint();
// Return `true` to let the map know that the image was updated.
return true;
}
};
map.addImage('pulsing-dot-red', pulsingDotRed, { pixelRatio: 2 });
map.addSource('dot-point-red', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': []
}
});
map.addLayer({
'id': 'dot-point-red',
'type': 'symbol',
'source': 'dot-point-red',
'layout': {
visibility: 'visible',
'icon-image': 'pulsing-dot-red',
'icon-allow-overlap' : true,
'icon-ignore-placement':true,
}
});
然后这个时候要注意一点,就是这个图层的位置,这个位置很讲究,因为他其实也是一个图层,他的位置必须放在所有点图层的下方,这样才会有一个图标,后面有这个脉冲点的效果。不然脉冲点在点图标的上面,看到的就不是这个感觉了。
这里可以参考我这篇博客,将这个脉冲点图层的位置移动到点定位图层的下方,就可以保证脉冲点图层永远处于所有点图层的下方了。
https://blog.csdn.net/Sakura1998gis/article/details/130545521?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171409878516800178580025%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=171409878516800178580025&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogfirst_rank_ecpm_v1~rank_v31_ecpm-3-130545521-null-null.nonecase&utm_term=%E5%AE%9A%E4%BD%8D&spm=1018.2226.3001.4450
然后生成点图层的时候,我们要找到我们想要重点关注的那个要素,这里我提供一个方法,参数1是图层的geojson,参数2是要根据那个字段来找最大值
//找到geojson中,指定属性的最大值的要素
const findFeatureWithMaxValue =(geojson, propertyName)=>{
// 首先确保geojson和propertyName是有效的
if (!geojson || !geojson.features || !propertyName) {
throw new Error('Invalid input: geojson or propertyName is missing');
}
// 初始化最大值和对应的feature
let maxValue = -Infinity;
let maxFeature = null;
// 遍历所有的features
geojson.features.forEach(function(feature) {
// 检查属性是否存在并且是数值类型
if (feature.properties && typeof feature.properties[propertyName] === 'number') {
const currentValue = feature.properties[propertyName];
// 如果当前值大于已知的最大值,则更新最大值和对应的feature
if (currentValue > maxValue) {
maxValue = currentValue;
maxFeature = feature;
}
}
});
// 返回具有最大属性值的feature
return maxFeature;
}
这个方法会将最大值的要素返回,返回之后,将这个要素的经纬度封装成一个点要素,塞进脉冲点图层中,就可以了。
if(maxFeature){
this.map.getSource('dot-point-red').setData({
"type": "FeatureCollection",
"features": [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates':[maxFeature.properties.lgtd,maxFeature.properties.lttd] // icon position [lng, lat]
}
}
]
})
}else{
this.map.getSource('dot-point-red').setData({
"type": "FeatureCollection",
"features": [
]
})
}