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

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

在這里插入圖片描述


在這里插入圖片描述

分析:

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

先在這里試試,在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;
 
		}

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

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

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

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庫請自備……