OpenLayers基础教程——要素的点选、框选、圈选、多边形选择
1、前言在OpenLayers中,框选功能需要ol.interaction.Select和ol.interaction.DragBox配合实现,其中前者主要负责盛放被选择的要素,后者主要负责矩形框的绘制,下面开始介绍。2、框选的实现框选功能的实现思路其实很简单,代码如下:<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtm
1、前言
本文来介绍一下OpenLayers
中点选
、框选
、圈选
、多边形选择
的实现方法,需要注意的是:
- 点选、框选对点、线、面三种要素均有效
- 圈选和多边形选择只对点要素有效
2、点选的实现
点选比较简单,创建一个ol.interaction.Select
对象,然后监听select
事件即可,代码如下:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>点选</title>
<link href="lib/ol/ol.css" rel="stylesheet" />
<script src="lib/ol/ol.js"></script>
</head>
<body>
<div id="map" style="width:800px;height:800px;"></div>
<h1 id="msg"></h1>
<script>
// 创建要素图层
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Polygon([[
[119.0, 29.0],
[119.2, 29.0],
[119.2, 29.2],
[119.0, 29.2],
[119.0, 29.0]
]]),
name: 'A'
}),
new ol.Feature({
geometry: new ol.geom.Polygon([[
[119.4, 29.0],
[119.6, 29.0],
[119.5, 29.2],
[119.4, 29.0]
]]),
name: 'B'
}),
new ol.Feature({
geometry: new ol.geom.LineString([
[119.0, 29.4],
[119.2, 29.3],
[119.4, 29.5],
[119.6, 29.3],
[119.8, 29.6]
]),
name: 'C'
}),
new ol.Feature({
geometry: new ol.geom.Point([119.4, 29.6]),
name: 'D'
}),
]
}),
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 30,
stroke: new ol.style.Stroke({
width: 4,
color: 'blue'
}),
fill: new ol.style.Fill({
color: 'yellow'
})
}),
stroke: new ol.style.Stroke({
width: 4,
color: 'blue'
}),
fill: new ol.style.Fill({
color: 'yellow'
})
})
});
// 创建地图
var map = new ol.Map({
target: 'map',
layers: [
vectorLayer,
],
view: new ol.View({
projection: 'EPSG:4326',
center: [119.2, 29.2],
zoom: 10
})
});
// 创建点选工具
var interaction = new ol.interaction.Select({
condition: ol.events.condition.singleClick,
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 30,
stroke: new ol.style.Stroke({
width: 4,
color: 'red'
}),
fill: new ol.style.Fill({
color: 'green'
})
}),
stroke: new ol.style.Stroke({
width: 4,
color: 'red'
}),
fill: new ol.style.Fill({
color: 'green'
})
}),
layers: [
vectorLayer
]
});
// 监听select事件
interaction.on('select', function (e) {
if (e.selected.length > 0) {
var feature = e.selected[0];
var name = feature.get('name');
document.getElementById('msg').innerText = '被选中的要素:' + name;
}
});
// 添加单选工具
map.addInteraction(interaction);
</script>
</body>
</html>
运行结果如下图所示:
点选的另一种实现方式就是监听地图事件,代码如下:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>点选</title>
<link href="lib/ol/ol.css" rel="stylesheet" />
<script src="lib/ol/ol.js"></script>
</head>
<body>
<div id="map" style="width:800px;height:800px;"></div>
<h1 id="msg"></h1>
<script>
// 选中样式
var selectedStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: 30,
stroke: new ol.style.Stroke({
width: 4,
color: 'red'
}),
fill: new ol.style.Fill({
color: 'green'
})
}),
stroke: new ol.style.Stroke({
width: 4,
color: 'red'
}),
fill: new ol.style.Fill({
color: 'green'
})
});
// 未选中样式
var unselectedStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: 30,
stroke: new ol.style.Stroke({
width: 4,
color: 'blue'
}),
fill: new ol.style.Fill({
color: 'yellow'
})
}),
stroke: new ol.style.Stroke({
width: 4,
color: 'blue'
}),
fill: new ol.style.Fill({
color: 'yellow'
})
});
// 创建要素图层
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Polygon([[
[119.0, 29.0],
[119.2, 29.0],
[119.2, 29.2],
[119.0, 29.2],
[119.0, 29.0]
]]),
name: 'A'
}),
new ol.Feature({
geometry: new ol.geom.Polygon([[
[119.4, 29.0],
[119.6, 29.0],
[119.5, 29.2],
[119.4, 29.0]
]]),
name: 'B'
}),
new ol.Feature({
geometry: new ol.geom.LineString([
[119.0, 29.4],
[119.2, 29.3],
[119.4, 29.5],
[119.6, 29.3],
[119.8, 29.6]
]),
name: 'C'
}),
new ol.Feature({
geometry: new ol.geom.Point([119.4, 29.6]),
name: 'D'
}),
]
}),
style: unselectedStyle
});
// 创建地图
var map = new ol.Map({
target: 'map',
layers: [
vectorLayer,
],
view: new ol.View({
projection: 'EPSG:4326',
center: [119.2, 29.2],
zoom: 10
})
});
// 注册地图事件
map.on('singleclick', function (e) {
var pixel = map.getEventPixel(e.originalEvent);
var currentFeature = map.forEachFeatureAtPixel(pixel, function (feature, layer) {
return feature;
});
if (currentFeature) {
var features = vectorLayer.getSource().getFeatures();
features.forEach(function (item) {
item.setStyle(unselectedStyle);
});
currentFeature.setStyle(selectedStyle);
var name = currentFeature.get('name');
document.getElementById('msg').innerText = '被选中的要素:' + name;
} else {
var features = vectorLayer.getSource().getFeatures();
features.forEach(function (item) {
item.setStyle(unselectedStyle);
});
}
});
</script>
</body>
</html>
运行结果如下图所示:
3、框选的实现
框选功能的实现思路很简单,ol.interaction.Draw
负责绘制矩形,ol.interaction.Select
用于盛放被选择的要素,代码如下:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>框选</title>
<link href="lib/ol/ol.css" rel="stylesheet" />
<script src="lib/ol/ol.js"></script>
</head>
<body>
<div id="map" style="width:800px;height:800px;"></div>
<h1 id="msg"></h1>
<script>
// 创建要素图层
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Polygon([[
[119.0, 29.0],
[119.2, 29.0],
[119.2, 29.2],
[119.0, 29.2],
[119.0, 29.0]
]]),
name: 'A'
}),
new ol.Feature({
geometry: new ol.geom.Polygon([[
[119.4, 29.0],
[119.6, 29.0],
[119.5, 29.2],
[119.4, 29.0]
]]),
name: 'B'
}),
new ol.Feature({
geometry: new ol.geom.LineString([
[119.0, 29.4],
[119.2, 29.3],
[119.4, 29.5],
[119.6, 29.3],
[119.8, 29.6]
]),
name: 'C'
}),
new ol.Feature({
geometry: new ol.geom.Point([119.4, 29.6]),
name: 'D'
}),
]
}),
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 30,
stroke: new ol.style.Stroke({
width: 4,
color: 'blue'
}),
fill: new ol.style.Fill({
color: 'yellow'
})
}),
stroke: new ol.style.Stroke({
width: 4,
color: 'blue'
}),
fill: new ol.style.Fill({
color: 'yellow'
})
})
});
// 创建绘制图层
var drawLayer = new ol.layer.Vector({
source: new ol.source.Vector(),
style: new ol.style.Style()
});
// 创建地图
var map = new ol.Map({
target: 'map',
layers: [
vectorLayer,
drawLayer
],
view: new ol.View({
projection: 'EPSG:4326',
center: [119.2, 29.2],
zoom: 10
})
});
// 创建选择工具,用于盛放矩形框内的要素
var select = new ol.interaction.Select({
condition: ol.events.condition.never,
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 30,
stroke: new ol.style.Stroke({
width: 4,
color: 'red'
}),
fill: new ol.style.Fill({
color: 'green'
})
}),
stroke: new ol.style.Stroke({
width: 4,
color: 'red'
}),
fill: new ol.style.Fill({
color: 'green'
})
})
});
// 创建绘制矩形工具
var drawBox = new ol.interaction.Draw({
source: drawLayer.getSource(),
type: 'Circle',
geometryFunction: ol.interaction.Draw.createBox()
});
// 开始绘制,清除已有要素
drawBox.on('drawstart', function () {
select.getFeatures().clear();
drawLayer.getSource().clear();
});
// 结束绘制
drawBox.on('drawend', function (e) {
if (e.feature) {
// 获取框选范围
var geometry = e.feature.getGeometry();
var extent = geometry.getExtent();
// 查询框选范围内的所有点
vectorLayer.getSource().forEachFeatureIntersectingExtent(extent, function (feature) {
select.getFeatures().push(feature);
});
// 遍历被选中的要素
var selected = [];
var selectedFeatures = select.getFeatures();
for (var i = 0; i < selectedFeatures.getLength(); i++) {
var feature = selectedFeatures.item(i);
var name = feature.get('name');
selected.push(name);
}
// 输出查询结果
var msg = selected.join('、');
document.getElementById('msg').innerText = '被选中的要素:' + msg;
}
});
// 添加交互工具
map.addInteraction(drawBox);
map.addInteraction(select);
</script>
</body>
</html>
运行结果如下图所示:
矩形框的绘制也可以使用ol.interaction.DragBox
来实现,代码如下:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>框选</title>
<link href="lib/ol/ol.css" rel="stylesheet" />
<script src="lib/ol/ol.js"></script>
</head>
<body>
<div id="map" style="width:800px;height:800px;"></div>
<h1 id="msg"></h1>
<script>
// 创建要素图层
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Polygon([[
[119.0, 29.0],
[119.2, 29.0],
[119.2, 29.2],
[119.0, 29.2],
[119.0, 29.0]
]]),
name: 'A'
}),
new ol.Feature({
geometry: new ol.geom.Polygon([[
[119.4, 29.0],
[119.6, 29.0],
[119.5, 29.2],
[119.4, 29.0]
]]),
name: 'B'
}),
new ol.Feature({
geometry: new ol.geom.LineString([
[119.0, 29.4],
[119.2, 29.3],
[119.4, 29.5],
[119.6, 29.3],
[119.8, 29.6]
]),
name: 'C'
}),
new ol.Feature({
geometry: new ol.geom.Point([119.4, 29.6]),
name: 'D'
}),
]
}),
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 30,
stroke: new ol.style.Stroke({
width: 4,
color: 'blue'
}),
fill: new ol.style.Fill({
color: 'yellow'
})
}),
stroke: new ol.style.Stroke({
width: 4,
color: 'blue'
}),
fill: new ol.style.Fill({
color: 'yellow'
})
})
});
// 创建地图
var map = new ol.Map({
target: 'map',
layers: [
vectorLayer,
],
view: new ol.View({
projection: 'EPSG:4326',
center: [119.2, 29.2],
zoom: 10
})
});
// 创建选择工具,用于盛放矩形框内的要素
var select = new ol.interaction.Select({
condition: ol.events.condition.never,
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 30,
stroke: new ol.style.Stroke({
width: 4,
color: 'red'
}),
fill: new ol.style.Fill({
color: 'green'
})
}),
stroke: new ol.style.Stroke({
width: 4,
color: 'red'
}),
fill: new ol.style.Fill({
color: 'green'
})
})
});
// 创建绘制工具
var dragBox = new ol.interaction.DragBox({
condition: ol.events.condition.always
});
// 开始绘制,清除已有要素
dragBox.on('boxstart', function () {
select.getFeatures().clear();
});
// 结束绘制
dragBox.on('boxend', function () {
// 获取被选择的要素
var extent = dragBox.getGeometry().getExtent();
vectorLayer.getSource().forEachFeatureIntersectingExtent(extent, function (feature) {
select.getFeatures().push(feature);
});
// 遍历被选中的要素
var selected = [];
var selectedFeatures = select.getFeatures();
for (var i = 0; i < selectedFeatures.getLength(); i++) {
var feature = selectedFeatures.item(i);
var name = feature.get('name');
selected.push(name);
}
// 输出查询结果
var msg = selected.join('、');
document.getElementById('msg').innerText = '被选中的要素:' + msg;
});
// 添加交互工具
map.addInteraction(dragBox);
map.addInteraction(select);
</script>
</body>
</html>
运行结果如下图所示:
4、圈选的实现
圈选功能的实现需要绕一个弯子,ol.interaction.Draw
负责绘制圆形,ol.interaction.Select
用于盛放被选择的要素,在绘制圆形后需要获取这个圆的外接矩形,利用外接矩形做第一次筛选,然后再利用内置的intersectsCoordinate(coordinates)
方法判断点是否在圆内部,代码如下:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>圈选</title>
<link href="lib/ol/ol.css" rel="stylesheet" />
<script src="lib/ol/ol.js"></script>
</head>
<body>
<div id="map" style="width:800px;height:800px;"></div>
<h1 id="msg"></h1>
<script>
// 创建要素图层
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Point([120.0, 30.0]),
name: 'A'
}),
new ol.Feature({
geometry: new ol.geom.Point([120.1, 30.1]),
name: 'B'
}),
new ol.Feature({
geometry: new ol.geom.Point([120.2, 30.2]),
name: 'C'
})
]
}),
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 30,
fill: new ol.style.Fill({
color: 'blue'
})
})
})
});
// 创建绘制图层
var drawLayer = new ol.layer.Vector({
source: new ol.source.Vector(),
style: new ol.style.Style()
});
// 创建地图
var map = new ol.Map({
target: 'map',
layers: [
vectorLayer,
drawLayer
],
view: new ol.View({
projection: 'EPSG:4326',
center: [120, 30],
zoom: 10
})
});
// 创建选择工具,用于盛放圆形内的要素
var select = new ol.interaction.Select({
condition: ol.events.condition.never,
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 30,
fill: new ol.style.Fill({
color: 'red'
})
})
})
});
// 创建绘制圆形工具
var drawBox = new ol.interaction.Draw({
source: drawLayer.getSource(),
type: 'Circle'
});
// 开始绘制,清除已有要素
drawBox.on('drawstart', function () {
select.getFeatures().clear();
drawLayer.getSource().clear();
});
// 结束绘制
drawBox.on('drawend', function (e) {
if (e.feature) {
// 获取圆的外接矩形范围
var circle = e.feature.getGeometry();
var extent = circle.getExtent();
// 查询外接矩形范围内的所有点
vectorLayer.getSource().forEachFeatureIntersectingExtent(extent, function (feature) {
var coordinates = feature.getGeometry().getCoordinates();
// 判断该点是否在圆内部
if (circle.intersectsCoordinate(coordinates)) {
select.getFeatures().push(feature);
}
});
// 遍历被选中的要素
var selected = [];
var selectedFeatures = select.getFeatures();
for (var i = 0; i < selectedFeatures.getLength(); i++) {
var feature = selectedFeatures.item(i);
var name = feature.get('name');
selected.push(name);
}
// 输出查询结果
var msg = selected.join('、');
document.getElementById('msg').innerText = '被选中的要素:' + msg;
}
});
// 添加交互工具
map.addInteraction(drawBox);
map.addInteraction(select);
</script>
</body>
</html>
运行结果如下图所示:
5、多边形选择的实现
多边形选择的实现方式和圈选类似,代码如下:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>多边形选择</title>
<link href="lib/ol/ol.css" rel="stylesheet" />
<script src="lib/ol/ol.js"></script>
</head>
<body>
<div id="map" style="width:800px;height:800px;"></div>
<h1 id="msg"></h1>
<script>
// 创建要素图层
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: new ol.geom.Point([120.0, 30.0]),
name: 'A'
}),
new ol.Feature({
geometry: new ol.geom.Point([120.1, 30.1]),
name: 'B'
}),
new ol.Feature({
geometry: new ol.geom.Point([120.2, 30.2]),
name: 'C'
})
]
}),
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 30,
fill: new ol.style.Fill({
color: 'blue'
})
})
})
});
// 创建绘制图层
var drawLayer = new ol.layer.Vector({
source: new ol.source.Vector(),
style: new ol.style.Style()
});
// 创建地图
var map = new ol.Map({
target: 'map',
layers: [
vectorLayer,
drawLayer
],
view: new ol.View({
projection: 'EPSG:4326',
center: [120, 30],
zoom: 10
})
});
// 创建选择工具,用于盛放多边形内的要素
var select = new ol.interaction.Select({
condition: ol.events.condition.never,
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 30,
fill: new ol.style.Fill({
color: 'red'
})
})
})
});
// 创建绘制多边形工具
var drawBox = new ol.interaction.Draw({
source: drawLayer.getSource(),
type: 'Polygon'
});
// 开始绘制,清除已有要素
drawBox.on('drawstart', function () {
select.getFeatures().clear();
drawLayer.getSource().clear();
});
// 结束绘制
drawBox.on('drawend', function (e) {
if (e.feature) {
// 获取多边形的外接矩形范围
var polygon = e.feature.getGeometry();
var extent = polygon.getExtent();
// 查询外接矩形范围内的所有点
vectorLayer.getSource().forEachFeatureIntersectingExtent(extent, function (feature) {
var coordinates = feature.getGeometry().getCoordinates();
// 判断该点是否在圆内部
if (polygon.intersectsCoordinate(coordinates)) {
select.getFeatures().push(feature);
}
});
// 遍历被选中的要素
var selected = [];
var selectedFeatures = select.getFeatures();
for (var i = 0; i < selectedFeatures.getLength(); i++) {
var feature = selectedFeatures.item(i);
var name = feature.get('name');
selected.push(name);
}
// 输出查询结果
var msg = selected.join('、');
document.getElementById('msg').innerText = '被选中的要素:' + msg;
}
});
// 添加交互工具
map.addInteraction(drawBox);
map.addInteraction(select);
</script>
</body>
</html>
运行结果如下图所示:
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)