图形绘制的基础是空间坐标,任何图形都是由空间坐标组成的。
一般有两种方式绘制图形:一种是空间坐标已知,通常根据已有的空间坐标信息直接添加图形,实现图形的绘制功能;另一种则是通过鼠标交互获取空间坐标,这也是图形绘制常用的方法,这种方法被称为交互式图形绘制。
目录
一、鼠标交互绘制图形的原理
交互式图形绘制的核心是对鼠标事件的监听,当点击鼠标或者移动鼠标时,则触发相应的事件,在对应事件的回调函数(ol.interaction.Draw的geometryFunction属性接受该回调函数)里,可获取所需的参数,如坐标信息,对获取的参数再进行相应的处理即可。在实现动态图形绘制时,主要对鼠标移动事件进行监听,当移动鼠标时,通过监听鼠标的移动事件,在移动事件的回调函数中获取鼠标当前的位置(空间坐标),然后根据鼠标坐标变化动态地绘制出一个临时的图形。
先初始化一个矢量绘制图层对象并添加到地图容器中,然后加载交互绘制矢量图形控件ol.interaction.Draw(在实例化时设置绘制类型:点、线、规则多边形、任意多边形,以及几何图形对应的特征参数),最后通过激活绘图图形控件在地图上绘制相应的几何图形。
二、编写基本代码
新建一个DrawFeatures.html页面,引用OpenLayers开发库,并加载OpenStreetMap瓦片地图。
添加几何图形绘制的功能能按钮,在此使用列表(select)设置绘制几何图形功能项。其中,类型为“无”时清除当前绘制的所有图形。
<body>
<div id="menu">
<label>几何图形类型: </label>
<select id="type">
<option value="None">无</option>
<option value="Point">点</option>
<option value="LineString">线</option>
<option value="Polygon">多边形</option>
<option value="Circle">圆</option>
<option value="Square">正方形</option>
<option value="Box">长方形</option>
</select>
</div>
<div id="map"></div>
<script>
var map = new ol.Map({
target: "map",
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
</script>
</body>
三、图形绘制功能代码
先在地图容器中添加一个矢量图层作为绘制层,然后实例化一个绘图控件对象(ol.interaction.Draw),并添加到地图容器中,根据设置的几何图形类型交互绘制图形。
var typeSelect = document.getElementById("type"); //绘制类型选择对象
var draw; //绘制控件对象
//实例化一个矢量图层Vector作为绘制层
var source = new ol.source.Vector({
wrapX: false
});
var vector = new ol.layer.Vector({
source: source,
style: new ol.style.Style({
fill: new ol.style.Fill({ //填充样式
color: "rgba(255, 255, 255, 0.2)"
}),
stroke: new ol.style.Stroke({ //边界样式
color: "#ffcc33",
width: 2
}),
image: new ol.style.Circle({ //点要素样式
radius: 7,
fill: new ol.style.Fill({
color: "#ffcc33"
})
})
})
});
map.addLayer(vector); //将绘制层添加到地图容器中
//用户更改绘制类型触发的事件
type.onchange = function(e){
map.removeInteraction(draw); //移除绘制图形
addInteraction(); //添加交互绘制功能控件
};
addInteraction(); //添加交互绘制功能控件
代码说明:在本示例中,加载一个矢量图层绘制层vector,在实例化此图层对象时统一设置了绘制的几何图形样式;然后通过调用addInteraction函数交互绘制图形控件(ol.interaction.Draw),实现基本几何图形的绘制功能。
几何图形绘制函数addInteraction的代码如下:
function addInteraction(){
var value = typeSelect.value; //绘制类型
if(value !== "None"){
if(source == null){
source = new ol.source.Vector({
wrapX: false
});
vector.setSource(source); //添加绘制层数据源
}
var geometryFunction, maxPoints;
if(value === "Square"){ //正方形
value = "Circle"; //设置绘制类型为Circle
//设置几何信息变更函数,即创建正多边形
geometryFunction = ol.interaction.Draw.createRegularPolygon(4);
}else if(value === "Box"){ //长方形
value = "LineString"; //设置绘制类型为LineString
maxPoints = 2; //设置最大点数为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;
};
}
//实例化交互绘制对象并添加到地图容器中
draw = new ol.interaction.Draw({
source: source, //绘制层数据源
type: value, //几何图形类型
geometryFunction: geometryFunction, //几何信息变更时的回调函数
maxPoints: maxPoints //最大点数
});
map.addInteraction(draw);
}else{
source = null;
vector.setSource(source); //清空绘制图形
}
}
代码说明:交互绘制几何图形的关键是实例化ol.interaction.Draw控件,设置其关键参数,并将此控件添加到地图容器中。支持点、线、圆、多边形图形,在创建交互控件时,直接设置控件对象的type参数即可;除此之外,正方形和长方形图形作为规则多边形,需要通过geometryFunction参数单独处理。
source:绘制图层的数据源,即承载几何图形要素的数据源。
type:绘制的几何图形类型,即ol.geom.GeometryType,包括Point、LineString、Polygon、MultiPoint、MultiLineString、MultiPolygon、Circle等。
geometryFunction:当几何坐标改变时调用此函数,当绘制类型为“正方形”和“长方形”时,需要通过此函数设置其几何对象,即为“正方形”时通过绘图控件对象的createRegularPolygon(4)创建,为“长方形“时则调用多边形(ol.geom.Polygon)的setCoordinates方法设置多边形的几何坐标串。
maxPoints:绘制图形结束前多边形或线的最大点数,线默认为2,多边形默认为3.
四、完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>绘制基本几何图形</title>
<link href="ol_v5.0.0/css/ol.css" rel="stylesheet" type="text/css" />
<script src="ol_v5.0.0/build/ol.js" type="text/javascript"></script>
</head>
<body>
<div id="menu">
<label>几何图形类型: </label>
<select id="type">
<option value="None">无</option>
<option value="Point">点</option>
<option value="LineString">线</option>
<option value="Polygon">多边形</option>
<option value="Circle">圆</option>
<option value="Square">正方形</option>
<option value="Box">长方形</option>
</select>
</div>
<div id="map"></div>
<script>
var map = new ol.Map({
target: "map",
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
var typeSelect = document.getElementById("type"); //绘制类型选择对象
var draw; //绘制控件对象
//实例化一个矢量图层Vector作为绘制层
var source = new ol.source.Vector({
wrapX: false
});
var vector = new ol.layer.Vector({
source: source,
style: new ol.style.Style({
fill: new ol.style.Fill({ //填充样式
color: "rgba(255, 255, 255, 0.2)"
}),
stroke: new ol.style.Stroke({ //边界样式
color: "#ffcc33",
width: 2
}),
image: new ol.style.Circle({ //点要素样式
radius: 7,
fill: new ol.style.Fill({
color: "#ffcc33"
})
})
})
});
map.addLayer(vector); //将绘制层添加到地图容器中
//用户更改绘制类型触发的事件
type.onchange = function(e){
map.removeInteraction(draw); //移除绘制图形
addInteraction(); //添加交互绘制功能控件
};
addInteraction(); //添加交互绘制功能控件
//根据绘制类型进行交互绘制
function addInteraction(){
var value = typeSelect.value; //绘制类型
if(value !== "None"){
if(source == null){
source = new ol.source.Vector({
wrapX: false
});
vector.setSource(source); //添加绘制层数据源
}
var geometryFunction, maxPoints;
if(value === "Square"){ //正方形
value = "Circle"; //设置绘制类型为Circle
//设置几何信息变更函数,即创建正多边形
geometryFunction = ol.interaction.Draw.createRegularPolygon(4);
}else if(value === "Box"){ //长方形
value = "LineString"; //设置绘制类型为LineString
maxPoints = 2; //设置最大点数为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;
};
}
//实例化交互绘制对象并添加到地图容器中
draw = new ol.interaction.Draw({
source: source, //绘制层数据源
type: value, //几何图形类型
geometryFunction: geometryFunction, //几何信息变更时的回调函数
maxPoints: maxPoints //最大点数
});
map.addInteraction(draw);
}else{
source = null;
vector.setSource(source); //清空绘制图形
}
}
</script>
</body>
</html>