openlayers 聚類分析中預警marker 的位置在縮放過程中出現偏移

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

							}

						}
					}
				}
			}

		}

	},

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章