OpenLayers 6 連點成線——限制只能在已有的點要素之間畫線

我們有時候會遇到這樣一種需求:地圖上已經產生了一些點,需要手動在這些點之間畫線連接。

 

分析:

我們知道OpenLayers原生的ol.interaction.Draw類型是無法支持這種限制的。於是仍然考慮在事件處理上找找機會:ol.interaction.Draw有一個屬性condition,它的定義是一個函數,接受event作爲參數(實際上只限於click類型的event),然後由函數的邏輯決定返回值ture還是false,以此通知控件是否處理本次點擊繪製。

實現:

先在這裏試試,在ol.interaction.Draw初始化的時候給condition賦值:

			condition: function(event) {
			let flag = 0;
			let features = map.getFeaturesAtPixel(event.pixel)
			features.some(element => {
				if (vSource.hasFeature(element)) {
					flag = 1;
					return true
				}
			});
			if (flag == 1) return true;

		}

先聲明一個標誌變量,然後用some對點擊到的所有要素進行部分遍歷(存在沒有點擊到的情況,所以用了一個標誌變量),使用了hasFeature來判斷迭代到的要素是不是我們目標圖層裏的點要素,如果是,就返回ture中斷迭代過程。

在外面判斷flag的值來確定上面的迭代過程有沒有命中目標圖層中的點要素,如果命中了,返回ture,通知draw組件“處理”本次點擊,連線。

爲了能準確點到目標圖層的點要素,還需要向地圖上添加一個snap交互組件,使得鼠標指針能夠自動吸附到附近的點要素:

var snap = new ol.interaction.Snap({
			source: vSource
		})
		map.addInteraction(draw);
		map.addInteraction(snap);

最後的效果就是:

全部代碼:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<script src="./js/v6/ol.js"></script>
	<link rel="stylesheet" href="./js/v6/ol.css">
</head>
<style>
	html,
	body {
		margin: 0;
		height: 100%;
	}
	#map {
		position: absolute;
		top: 0;
		bottom: 0;
		width: 100%;
	}
</style>
<body>
	<div id="map"></div>
	<script>
		var map = new ol.Map({
			layers: [
				new ol.layer.Tile({
					source: new ol.source
						.XYZ({
							url: "http://www.google.cn/maps/vt?lyrs=s&amp&x={x}&y={y}&z={z}"
						})
				})
			],
			target: 'map',
			view: new ol.View({
				center: [12956634.642942,
					4851883.963394
				],
				zoom: 12
			})
		});
		var pointA = [];
		for (var i = 0; i < 10; i++) {
			let x = Math.random() * 20000 + 12946634.642942;
			let y = Math.random() * 20000 + 4841883.963394;
			pointA.push(
				new ol.Feature(
					new ol.geom.Point([x, y])
				)
			)
			pointA[i].setStyle(
				new ol.style.Style({
					image: new ol.style.Circle({
						radius: 5,
						fill: new ol.style.Fill({
							color: '#FF0'
						})
					})
				})
			)
		}
		var vSource = new ol.source.Vector();
		var vLayer = new ol.layer.Vector({
			source: vSource
		})
		var vvSource = new ol.source.Vector();
		var vvLayer = new ol.layer.Vector({
			source: vvSource,
			style: new ol.style.Style({
				image: new ol.style.Circle({
					radius: 5,
					fill: new ol.style.Fill({
						color: '#FF0'
					})
				}),
				stroke: new ol.style.Stroke({
					color: '#FF0',
					width: 3
				})
			})
		})
		vSource.addFeatures(pointA);
		map.addLayer(vLayer)
		map.addLayer(vvLayer)
		var draw = new ol.interaction.Draw({
			type: 'LineString',
			source: vvSource,
			sourceConstrain: vSource,
			style: new ol.style.Style({
				image: new ol.style.Circle({
					radius: 8,
					fill: new ol.style.Fill({
						color: '#FF0'
					})
				}),
				stroke: new ol.style.Stroke({
					color: '#FF0',
					width: 3
				})
			}),
			condition: function(event) {
			let flag = 0;
			let features = map.getFeaturesAtPixel(event.pixel)
			features.some(element => {
				if (vSource.hasFeature(element)) {
					flag = 1;
					return true
				}
			});
			if (flag == 1) return true;
		}
		});
		var snap = new ol.interaction.Snap({
			source: vSource
		})
		map.addInteraction(draw);
		map.addInteraction(snap);
	</script>
</body>
</html>

ol庫請自備……


我在企鵝家的課堂和CSDN學院都開通了《OpenLayers實例詳解》課程,歡迎報名學習。搜索關鍵字OpenLayers就能看到。

 

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