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就能看到。

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

战斗中的老胡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值