OpenLayers 6 連點(diǎn)成線——限制只能在已有的點(diǎn)要素之間畫(huà)線
我們有時(shí)候會(huì)遇到這樣一種需求:地圖上已經(jīng)產(chǎn)生了一些點(diǎn),需要手動(dòng)在這些點(diǎn)之間畫(huà)線連接。


分析:
我們知道OpenLayers原生的ol.interaction.Draw類型是無(wú)法支持這種限制的。于是仍然考慮在事件處理上找找機(jī)會(huì):ol.interaction.Draw有一個(gè)屬性condition,它的定義是一個(gè)函數(shù),接受event作為參數(shù)(實(shí)際上只限于click類型的event),然后由函數(shù)的邏輯決定返回值ture還是false,以此通知控件是否處理本次點(diǎn)擊繪制。
實(shí)現(xiàn):
先在這里試試,在ol.interaction.Draw初始化的時(shí)候給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;
}
先聲明一個(gè)標(biāo)志變量,然后用some對(duì)點(diǎn)擊到的所有要素進(jìn)行部分遍歷(存在沒(méi)有點(diǎn)擊到的情況,所以用了一個(gè)標(biāo)志變量),使用了hasFeature來(lái)判斷迭代到的要素是不是我們目標(biāo)圖層里的點(diǎn)要素,如果是,就返回ture中斷迭代過(guò)程。
在外面判斷flag的值來(lái)確定上面的迭代過(guò)程有沒(méi)有命中目標(biāo)圖層中的點(diǎn)要素,如果命中了,返回ture,通知draw組件“處理”本次點(diǎn)擊,連線。
為了能準(zhǔn)確點(diǎn)到目標(biāo)圖層的點(diǎn)要素,還需要向地圖上添加一個(gè)snap交互組件,使得鼠標(biāo)指針能夠自動(dòng)吸附到附近的點(diǎn)要素:
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&&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庫(kù)請(qǐng)自備……