问题:在做疫情分析时,疫情点采用cluster动态聚集,对于有肺炎患者的地方,通过overlay的方式显示动态闪烁点,但是由于疫情点是动态聚集的,在不同的级别,聚集点不同,下一次聚集时,有肺炎患者的点被聚集到另一个聚集点中,但是预警闪烁点的位置还在原地,这样就造成预警点不在有肺炎患者的聚集点中。
解决办法:当新出现肺炎患者点,将其加入到聚集图层中,同时添加overlay 预警点,并将肺炎患者点的实际id和位置保存到overlay的属性中。
1、新出现肺炎患者点,将其加入到聚集图层中(这是是加入到数据中,情况图层数据,再统一加载新的数据)
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
var id = row.resourceid;
var val = row.temperature;
var region = row.retrievalRegion;
var pnt = [ row.channelLongitude, row.channelLatitude];
var fea = new ol.Feature(new ol.geom.Point(pnt))
fea.setId(id);
fea.setProperties(row);
feas.push(fea);
}
var sr = this.clusterLyr.getSource().getSource();
sr.clear();
sr.addFeatures(feas);//聚类要素展示数据
sr.refresh();
2、同时添加overlay 预警点,并将肺炎患者点的实际id和位置保存到overlay的属性中
var id = "n_alert" + this.refNum;
var css = "n_alert active";
var msg = "";
var showClose = false;
var autoClose = 4000;
var str = "发现【1】例新冠肺炎患者";
var center = [ d1[0].channelLongitude, d1[0].channelLatitude ];
if (true) {
var div = document.createElement('div');
div.className = css;
div.id = id;
var indiv = document.createElement('div');
div.appendChild(indiv);
var p = document.createElement('p');
var span = document.createElement('span');
indiv.appendChild(p);
indiv.appendChild(span);
var mkId = this.alertId;
var cFea = this.clusterLyr.getSource().getClosestFeatureToCoordinate(center);
var newPos = center;
if (cFea) {
var feas = cFea.get("features");
if (feas && feas.length > 0) {
for (var i = 0; i < feas.length; i++) {
var coord = feas[i].getGeometry().getCoordinates();
if (feas[i].getId() == d1[0].resourceid) {
newPos = cFea.getGeometry().getCoordinates();
break;
}
}
}
}
var marker = new ol.Overlay({
element : div,
id : mkId,
position : newPos,
positioning : 'center-center'
});
// 记录要素的id
marker.setProperties({
center : center,
isAlert : true,
resourceid : d1[0].resourceid
});
map.addOverlay(marker);
3、在样式函数中添加聚类处理,在聚类函数中添加预警点
styleFunction : function(feature, resolution, isHover) {
if (resolution != this.currentRes) {
this.calCluster(resolution);
this.currentRes = resolution;
} else {
if (this.refresh == true) {
this.calCluster(resolution);
this.refresh = false;
}
}
3、在聚类函数中,添加预警点处理(每一次重新聚类后,就会重新处理预警点的位置)
var this_ = this;
setTimeout(function() {
this_.calAlert();//处理预警marker
}, 300);
即基于预警的要素的center利用函数getClosestFeatureToCoordinate(注意,这里要用回调函数,在函数中通过预警的要素的resourceid过滤返回离center最近且包含resourceid要素的聚集点)得到该预警点预警的要素当前所在的聚集点,然后获得此聚集点的中心位置,将中心位置赋给预警的overlay,并根据次聚集点的大小,重新计算预警overlay的半径
//计算预警marker
calAlert : function() {
var s = map.getOverlays();
if (s && s.getArray()) {
var all = s.getArray();
if (all && all.length > 0) {
for (var i = 0; i < all.length; i++) {
if (all[i].get("isAlert") == true) {
var center = all[i].get("center");
var id = all[i].get("resourceid");
var cFea = this.clusterLyr.getSource().getClosestFeatureToCoordinate(center, function(e) {
var temps = e.get("features");
var flag = false;
for (var t = 0; t < temps.length; t++) {
if (id == temps[t].getId()) {
flag = true;
return e;
}
}
});
if (cFea) {
var feas = cFea.get("features");
if (feas && feas.length > 0) {
for (var j = 0; j < feas.length; j++) {
if (id == feas[j].getId()) {
var pos = cFea.getGeometry().getCoordinates();
all[i].setPosition(pos);
var ele = all[i].getElement();
if (ele) {
var l = feas.length;
if (l > 20) {
$(ele).removeClass("alert_1").removeClass("alert_2").removeClass("alert_3").addClass("alert_3");
} else if (l > 10) {
$(ele).removeClass("alert_1").removeClass("alert_2").removeClass("alert_3").addClass("alert_2");
} else if (l > 5) {
$(ele).removeClass("alert_1").removeClass("alert_2").removeClass("alert_3").addClass("alert_2");
} else {
$(ele).removeClass("alert_1").removeClass("alert_2").removeClass("alert_3");
}
}
break;
}
}
}
}
}
}
}
}
},