問題:在做疫情分析時,疫情點採用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;
}
}
}
}
}
}
}
}
},