原文链接及内容

运行界面

此示例演示如何使用DragBox交互组件来选择要素,被选择的要素会被添加到选择交互的要素覆盖层(ol/Interactive/Select)中,用于高亮显示。按住Ctrl键并拖动(在Mac上按住Command键并拖动)可绘制出框。

main.js代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import GeoJSON from 'ol/format/GeoJSON.js';
import Map from 'ol/Map.js';
import VectorLayer from 'ol/layer/Vector.js';
import VectorSource from 'ol/source/Vector.js';
import View from 'ol/View.js';
import {DragBox, Select} from 'ol/interaction.js';
import {Fill, Stroke, Style} from 'ol/style.js';
import {platformModifierKeyOnly} from 'ol/events/condition.js';

const vectorSource = new VectorSource({
url: 'https://openlayers.org/data/vector/ecoregions.json',
format: new GeoJSON(),
});

const style = new Style({
fill: new Fill({
color: '#eeeeee',
}),
});

const map = new Map({
layers: [
new VectorLayer({
source: vectorSource,
background: '#1a2b39',
style: function (feature) {
const color = feature.get('COLOR_BIO') || '#eeeeee';
style.getFill().setColor(color);
return style;
},
}),
],
target: 'map',
view: new View({
center: [0, 0],
zoom: 2,
constrainRotation: 16,
}),
});

const selectedStyle = new Style({
fill: new Fill({
color: 'rgba(255, 255, 255, 0.6)',
}),
stroke: new Stroke({
color: 'rgba(255, 255, 255, 0.7)',
width: 2,
}),
});

// a normal select interaction to handle click
// 一个正常用于处理点击的选择交互组件
const select = new Select({
style: function (feature) {
const color = feature.get('COLOR_BIO') || '#eeeeee';
selectedStyle.getFill().setColor(color);
return selectedStyle;
},
});
map.addInteraction(select);

const selectedFeatures = select.getFeatures();

// a DragBox interaction used to select features by drawing boxes
// 通过绘制框来选择要素的DragBox交互组件
const dragBox = new DragBox({
condition: platformModifierKeyOnly,
});

map.addInteraction(dragBox);

dragBox.on('boxend', function () {
const extent = dragBox.getGeometry().getExtent();
const boxFeatures = vectorSource
.getFeaturesInExtent(extent)
.filter((feature) => feature.getGeometry().intersectsExtent(extent));

// features that intersect the box geometry are added to the
// collection of selected features
// 与方框几何相交的要素将被添加到所选要素集合中

// if the view is not obliquely rotated the box geometry and
// its extent are equalivalent so intersecting features can
// be added directly to the collection
// 如果视图没有倾斜旋转,则方框的几何图形与其范围相等,因此可以将与方框相交的要素直接添加到集合中
const rotation = map.getView().getRotation();
const oblique = rotation % (Math.PI / 2) !== 0;

// when the view is obliquely rotated the box extent will
// exceed its geometry so both the box and the candidate
// feature geometries are rotated around a common anchor
// to confirm that, with the box geometry aligned with its
// extent, the geometries intersect
// 当视图倾斜旋转时,框的范围将超过它的几何图形,因此框和候选要素的几何图形都围绕一个公共锚点旋转,
// 以确认当框的几何图形与它的范围对齐时,几何图形将相交
if (oblique) {
const anchor = [0, 0];
const geometry = dragBox.getGeometry().clone();
geometry.rotate(-rotation, anchor);
const extent = geometry.getExtent();
boxFeatures.forEach(function (feature) {
const geometry = feature.getGeometry().clone();
geometry.rotate(-rotation, anchor);
if (geometry.intersectsExtent(extent)) {
selectedFeatures.push(feature);
}
});
} else {
selectedFeatures.extend(boxFeatures);
}
});

// clear selection when drawing a new box and when clicking on the map
// 在绘制新框和在地图上单击时清除选择
dragBox.on('boxstart', function () {
selectedFeatures.clear();
});

const infoBox = document.getElementById('info');

selectedFeatures.on(['add', 'remove'], function () {
const names = selectedFeatures.getArray().map(function (feature) {
return feature.get('ECO_NAME');
});
if (names.length > 0) {
infoBox.innerHTML = names.join(', ');
} else {
infoBox.innerHTML = 'None';
}
});

界面布局文件index.html代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Box Selection</title>
<link rel="stylesheet" href="node_modules/ol/ol.css">
<style>
.map {
width: 100%;
height: 400px;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
<div>Selected regions: <span id="info">None</span></div>
<!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
<script src="https://cdn.jsdelivr.net/npm/elm-pep@1.0.6/dist/elm-pep.js"></script>
<script type="module" src="main.js"></script>
</body>
</html>