1、前言
前面的博客其实已经介绍过了如何在openlayers
中绘制图形,不过那是基于已有的坐标进行绘制。很多时候,用户往往需要使用鼠标自行在地图上进行图形绘制,这就涉及到了openlayers
中的地图交互功能,下面开始介绍。
2、绘制基础图形
在openlayers
中,实现地图交互的类是ol.interaction
,默认情况下,openlayers
只支持Point(点)
、LineString(线)
、Polygon(面)
、Circle(圆)
这四种基本图形。下面一段代码实现了这四种基本图形的绘制:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8" />
<title>OpenLayers</title>
<style>
html, body, #map {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#group {
position: absolute;
right: 20px;
top: 20px;
z-index: 200;
}
</style>
<!-- openlayers -->
<link href="libs/ol/ol.css" rel="stylesheet" />
<script src="libs/ol/ol.js"></script>
<!-- bootstrap -->
<link href="libs/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<script src="libs/bootstrap/js/jquery-3.4.1.min.js"></script>
<script src="libs/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<div id="map">
<div id="group" class="btn-group">
<button id="point" type="button" class="btn btn-primary">画点</button>
<button id="lineString" type="button" class="btn btn-success">画线</button>
<button id="polygon" type="button" class="btn btn-warning">画面</button>
<button id="circle" type="button" class="btn btn-info">画圆</button>
<button id="stop" type="button" class="btn btn-danger">结束</button>
</div>
</div>
<script>
// 创建图层
var source = new ol.source.Vector();
var layer = new ol.layer.Vector({
source: source
});
// 创建地图
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
layer
],
view: new ol.View({
projection: 'EPSG:4326',
center: [120, 30],
zoom: 8
})
});
//
var draw;
// 绘制点
$('#point').click(function () {
if (draw != undefined && draw != null) {
map.removeInteraction(draw);
}
draw = new ol.interaction.Draw({
source: source,
type: 'Point',
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
})
})
});
map.addInteraction(draw);
})
// 绘制线
$('#lineString').click(function () {
if (draw != undefined && draw != null) {
map.removeInteraction(draw);
}
draw = new ol.interaction.Draw({
source: source,
type: 'LineString',
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
}),
stroke: new ol.style.Stroke({
color: 'yellow',
width: 2
})
})
});
map.addInteraction(draw);
})
// 绘制面
$('#polygon').click(function () {
if (draw != undefined && draw != null) {
map.removeInteraction(draw);
}
draw = new ol.interaction.Draw({
source: source,
type: 'Polygon',
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
}),
stroke: new ol.style.Stroke({
color: 'yellow',
width: 2
}),
fill: new ol.style.Fill({
color: 'blue'
})
})
});
map.addInteraction(draw);
})
// 绘制圆
$('#circle').click(function () {
if (draw != undefined && draw != null) {
map.removeInteraction(draw);
}
draw = new ol.interaction.Draw({
source: source,
type: 'Circle',
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
}),
stroke: new ol.style.Stroke({
color: 'yellow',
width: 2
}),
fill: new ol.style.Fill({
color: 'blue'
})
})
});
map.addInteraction(draw);
})
// 结束绘制
$('#stop').click(function () {
if (draw != undefined && draw != null) {
map.removeInteraction(draw);
}
})
</script>
</body>
</html>
运行结果如下图所示:
3、设置图形样式
我们也可以对绘制的图形的样式进行设置,还是老方法:创建layer时指定样式即可
。代码如下:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8" />
<title>OpenLayers</title>
<style>
html, body, #map {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#group {
position: absolute;
right: 20px;
top: 20px;
z-index: 200;
}
</style>
<!-- openlayers -->
<link href="libs/ol/ol.css" rel="stylesheet" />
<script src="libs/ol/ol.js"></script>
<!-- bootstrap -->
<link href="libs/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<script src="libs/bootstrap/js/jquery-3.4.1.min.js"></script>
<script src="libs/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<div id="map">
<div id="group" class="btn-group">
<button id="point" type="button" class="btn btn-primary">画点</button>
<button id="lineString" type="button" class="btn btn-success">画线</button>
<button id="polygon" type="button" class="btn btn-warning">画面</button>
<button id="circle" type="button" class="btn btn-info">画圆</button>
<button id="stop" type="button" class="btn btn-danger">结束</button>
</div>
</div>
<script>
// 创建图层
var source = new ol.source.Vector();
var layer = new ol.layer.Vector({
source: source,
style: function (feature, resolution) {
var style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
}),
stroke: new ol.style.Stroke({
color: 'green',
width: 2
}),
fill: new ol.style.Fill({
color: 'skyblue'
})
});
return style;
}
});
// 创建地图
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
layer
],
view: new ol.View({
projection: 'EPSG:4326',
center: [120, 30],
zoom: 8
})
});
//
var draw;
// 绘制点
$('#point').click(function () {
if (draw != undefined && draw != null) {
map.removeInteraction(draw);
}
draw = new ol.interaction.Draw({
source: source,
type: 'Point',
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
})
})
});
map.addInteraction(draw);
})
// 绘制线
$('#lineString').click(function () {
if (draw != undefined && draw != null) {
map.removeInteraction(draw);
}
draw = new ol.interaction.Draw({
source: source,
type: 'LineString',
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
}),
stroke: new ol.style.Stroke({
color: 'yellow',
width: 2
})
})
});
map.addInteraction(draw);
})
// 绘制面
$('#polygon').click(function () {
if (draw != undefined && draw != null) {
map.removeInteraction(draw);
}
draw = new ol.interaction.Draw({
source: source,
type: 'Polygon',
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
}),
stroke: new ol.style.Stroke({
color: 'yellow',
width: 2
}),
fill: new ol.style.Fill({
color: 'blue'
})
})
});
map.addInteraction(draw);
})
// 绘制圆
$('#circle').click(function () {
if (draw != undefined && draw != null) {
map.removeInteraction(draw);
}
draw = new ol.interaction.Draw({
source: source,
type: 'Circle',
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
}),
stroke: new ol.style.Stroke({
color: 'yellow',
width: 2
}),
fill: new ol.style.Fill({
color: 'blue'
})
})
});
map.addInteraction(draw);
})
// 绘制预案
$('#stop').click(function () {
if (draw != undefined && draw != null) {
map.removeInteraction(draw);
}
})
</script>
</body>
</html>
运行结果如下图所示:
4、设置捕捉距离
假设现在绘制一个四边形,那么有两种方式可以结束绘制:1、画到第四个点时双击鼠标
、2、第四个点绘制完后回到第一个点,使之成为一个封闭图形
。如果是用第二种方式,我们可以设置捕捉距离
,以实现精确绘制,代码如下:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8" />
<title>OpenLayers</title>
<style>
html, body, #map {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#group {
position: absolute;
right: 20px;
top: 20px;
z-index: 200;
}
</style>
<!-- openlayers -->
<link href="libs/ol/ol.css" rel="stylesheet" />
<script src="libs/ol/ol.js"></script>
<!-- bootstrap -->
<link href="libs/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<script src="libs/bootstrap/js/jquery-3.4.1.min.js"></script>
<script src="libs/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<div id="map">
<div id="group" class="btn-group">
<button id="polygon" type="button" class="btn btn-primary">画面</button>
</div>
</div>
<script>
// 创建图层
var source = new ol.source.Vector();
var layer = new ol.layer.Vector({
source: source,
style: function (feature, resolution) {
var style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
}),
stroke: new ol.style.Stroke({
color: 'green',
width: 2
}),
fill: new ol.style.Fill({
color: 'skyblue'
})
});
return style;
}
});
// 创建地图
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
layer
],
view: new ol.View({
projection: 'EPSG:4326',
center: [120, 30],
zoom: 8
})
});
//
var draw;
// 绘制面
$('#polygon').click(function () {
if (draw != undefined && draw != null) {
map.removeInteraction(draw);
}
draw = new ol.interaction.Draw({
source: source,
type: 'Polygon',
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
}),
stroke: new ol.style.Stroke({
color: 'yellow',
width: 2
}),
fill: new ol.style.Fill({
color: 'blue'
})
}),
snapTolerance: 40
});
map.addInteraction(draw);
})
</script>
</body>
</html>
我在这里将捕捉的距离设置为40像素,大家可以试一试,如果用第二种方式进行绘制,最后一个点会被捕捉移到第一个点的位置。
5、绘制三角形
使用上面的代码其实可以完成三角形的绘制,但我们还有另一个方法,那就是使用maxPoints
属性,该属性规定了绘制的多边形最多包含几个点,这样就能帮我们自动完成三角形的绘制,代码如下:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8" />
<title>OpenLayers</title>
<style>
html, body, #map {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#group {
position: absolute;
right: 20px;
top: 20px;
z-index: 200;
}
</style>
<!-- openlayers -->
<link href="libs/ol/ol.css" rel="stylesheet" />
<script src="libs/ol/ol.js"></script>
<!-- bootstrap -->
<link href="libs/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<script src="libs/bootstrap/js/jquery-3.4.1.min.js"></script>
<script src="libs/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<div id="map">
<div id="group" class="btn-group">
<button id="triangle" type="button" class="btn btn-primary">画三角形</button>
</div>
</div>
<script>
// 创建图层
var source = new ol.source.Vector();
var layer = new ol.layer.Vector({
source: source,
style: function (feature, resolution) {
var style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
}),
stroke: new ol.style.Stroke({
color: 'green',
width: 2
}),
fill: new ol.style.Fill({
color: 'greenyellow'
})
});
return style;
}
});
// 创建地图
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
layer
],
view: new ol.View({
projection: 'EPSG:4326',
center: [120, 30],
zoom: 8
})
});
var draw;
// 绘制三角形
$('#triangle').click(function () {
if (draw != undefined && draw != null) {
map.removeInteraction(draw);
}
draw = new ol.interaction.Draw({
source: source,
type: 'Polygon',
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
}),
stroke: new ol.style.Stroke({
color: 'yellow',
width: 2
}),
fill: new ol.style.Fill({
color: 'blue'
})
}),
maxPoints: 3
});
map.addInteraction(draw);
})
</script>
</body>
</html>
运行结果如下图所示:
6、绘制正多边形
正多边形是以圆
为基础进行绘制的图形,下面代码实现了正三角形
、正方形
、正五边形
、正六边形
的绘制:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8" />
<title>OpenLayers</title>
<style>
html, body, #map {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#group {
position: absolute;
right: 20px;
top: 20px;
z-index: 200;
}
</style>
<!-- openlayers -->
<link href="libs/ol/ol.css" rel="stylesheet" />
<script src="libs/ol/ol.js"></script>
<!-- bootstrap -->
<link href="libs/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<script src="libs/bootstrap/js/jquery-3.4.1.min.js"></script>
<script src="libs/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<div id="map">
<div id="group" class="btn-group">
<button type="button" class="btn btn-primary" onclick="drawRegularPolygon(3)">三角形</button>
<button type="button" class="btn btn-success" onclick="drawRegularPolygon(4)">正方形</button>
<button type="button" class="btn btn-warning" onclick="drawRegularPolygon(5)">正五边形</button>
<button type="button" class="btn btn-info" onclick="drawRegularPolygon(6)">正六边形</button>
<button type="button" class="btn btn-danger" onclick="removeDraw()">结束</button>
</div>
</div>
<script>
// 创建图层
var source = new ol.source.Vector();
var layer = new ol.layer.Vector({
source: source,
style: function (feature, resolution) {
var style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
}),
stroke: new ol.style.Stroke({
color: 'green',
width: 2
}),
fill: new ol.style.Fill({
color: 'Crimson'
})
});
return style;
}
});
// 创建地图
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
layer
],
view: new ol.View({
projection: 'EPSG:4326',
center: [120, 30],
zoom: 8
})
});
// 绘制正多边形
var draw;
function drawRegularPolygon(pointNumber) {
if (draw != undefined && draw != null) {
map.removeInteraction(draw);
}
draw = new ol.interaction.Draw({
source: source,
type: 'Circle',
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
}),
stroke: new ol.style.Stroke({
color: 'yellow',
width: 2
}),
fill: new ol.style.Fill({
color: 'blue'
})
}),
geometryFunction: ol.interaction.Draw.createRegularPolygon(pointNumber)
});
map.addInteraction(draw);
}
// 绘制预案
function removeDraw() {
if (draw != undefined && draw != null) {
map.removeInteraction(draw);
}
}
</script>
</body>
</html>
运行结果如下图所示:
7、绘制矩形
矩形的绘制较为特殊,需要用到maxPoints
和geometryFunction
这两个属性,同时以LineString
的形式进行绘制,代码如下:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta charset="utf-8" />
<title>OpenLayers</title>
<style>
html, body, #map {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#group {
position: absolute;
right: 20px;
top: 20px;
z-index: 200;
}
</style>
<!-- openlayers -->
<link href="libs/ol/ol.css" rel="stylesheet" />
<script src="libs/ol/ol.js"></script>
<!-- bootstrap -->
<link href="libs/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<script src="libs/bootstrap/js/jquery-3.4.1.min.js"></script>
<script src="libs/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<div id="map">
<div id="group" class="btn-group">
<button id="rectangle" type="button" class="btn btn-primary">绘制矩形</button>
</div>
</div>
<script>
// 创建图层
var source = new ol.source.Vector();
var layer = new ol.layer.Vector({
source: source,
style: function (feature, resolution) {
var style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
}),
stroke: new ol.style.Stroke({
color: 'green',
width: 2
}),
fill: new ol.style.Fill({
color: 'DarkViolet'
})
});
return style;
}
});
// 创建地图
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
layer
],
view: new ol.View({
projection: 'EPSG:4326',
center: [120, 30],
zoom: 8
})
});
var draw;
// 绘制正三角形
$('#rectangle').click(function () {
if (draw != undefined && draw != null) {
map.removeInteraction(draw);
}
draw = new ol.interaction.Draw({
source: source,
type: 'LineString',
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: 'red'
})
}),
stroke: new ol.style.Stroke({
color: 'yellow',
width: 2
}),
fill: new ol.style.Fill({
color: 'blue'
})
}),
maxPoint: 2,
geometryFunction: function (coordinates, geometry) {
if (!geometry) {
geometry = new ol.geom.Polygon(null);
}
var start = coordinates[0];
var end = coordinates[1];
geometry.setCoordinates([
[
start,
[start[0], end[1]],
end,
[end[0], start[1]],
start
]
]);
return geometry;
}
});
map.addInteraction(draw);
})
</script>
</body>
</html>
运行结果如下图所示:
8、结语
在openlayers
中,基础图形的绘制很简单,只需要设置不同的type
即可。而特殊的图形,诸如正方形
、矩形
等则需要借助ol.interaction.Draw
中的一些属性和方法实现。