数据加载原理
GIS地图加载的一般原理
在web端加载切片地图和矢量地图的原理基本相同
(1)瓦片地图。在web端加载瓦片地图一般有两种方式。一种为直接读取缓存加载,也就是说直接读取硬盘中存储的瓦片图片,另一种为调用瓦片地图接口,例如Arcgis Server、GeoServer等.。
加载原理:通过Ajax请求瓦片地图服务或数据,根据瓦片地图的级数、行列号分别获取对应的瓦片地图,将其按照请求的控件范围组织好,从而形成一张地图进行展示
(2)矢量地图。在web端加载矢量地图,一般也有两种,一种为直接读取矢量地图文件,即存储在硬盘中的GML、KML等格式的矢量地图文件。另一种方式为调用矢量地图服务接口,通过接口加载矢量地图
加载原理:通过Ajax请求矢量地图服务或数据,根据请求到的矢量地图,在Web端实时生成矢量地图并显示在网页中。
基础地图数据
在这里我们是基于ArcGis数据为例进行演示,针对ArcGis的数据,openLayers封装了一个ArcGis瓦片数据源可以直接使用,同时,可以基于OpenLayers现有通用的图层与数据源,加载其瓦片地图或者矢量地图
下面是基于ArcGis Server REST的瓦片地图服务接口
window.onload = function () {
var mousePositionControl = new ol.control.MousePosition({
//坐标格式
coordinateFormat:ol.coordinate.createStringXY(4),
//地图投影坐标
projection:'EPSG:4326',
//坐标信息显示样式
className:'custom-mouse-position',
//显示鼠标位置信息的目标地图容器
target:document.getElementById('mouse-position'),
//未定义坐标的标记
undefinedHTML:' '
});
//实例化ArcGis Server
var arcGISSource = new ol.source.TileArcGISRest({
url: 'http://localhost:6080/arcgis/rest/services/Map/MapServer',//输入自己的服务地址
});
var arcGISLayers = new ol.layer.Tile({
source: arcGISSource
//extend:[-13884991,2870341,-7455066,6338219]
});
//实例化Map对象并加载地图
var map = new ol.Map({
//容器div层的ID
target: 'map',
//地图容器中加载的图层
layers: [],
//地图图视的设置
view: new ol.View({
//地图中心点
center: [117.4250, 39.0890],
zoom: 15,
projection: 'EPSG:4326'
}),
//加载控件到地图容器中
controls: ol.control.defaults({}).extend([mousePositionControl])
});
map.addLayer(arcGISLayers);
}
通过调用接口呈现的样子如下图
上面是调用的ArcGis的瓦片地图服务接口,openlayers不仅可以调用切片服务,还可以对ArcGis Serve Rest的矢量地图服务接口和ArcGis Online的瓦片地图服务接口,在这就不演示了,百度一大片
其它地图数据
初次之外,我们还可以使用一些开放数据。包括KML、GML、GPX、GeoJSON等,具体是什么我们可以包都得知,其实我们平常用到最多的就是公共地图数据,包括Bing地图、OpenStreetMap、百度地图、高德地图、谷歌地图等。
下面总结下加载这些地图source
OpenStreetMap
source:new ol.source.OSM()
Bing地图
var key="申请密钥"l
var roads = new ol.layer.Tile({
source:new ol.source.BingMaps({key:key,imagerySet:'Road'})
})
百度地图
var baidu_source = new ol.source.TileImage({
projection: projection,
tileGrid: tilegrid,
tileUrlFunction: function(tileCoord, pixelRatio, proj){
if(!tileCoord){
return "";
}
var z = tileCoord[0];
var x = tileCoord[1];
var y = tileCoord[2];
if(x<0){
x = "M"+(-x);
}
if(y<0){
y = "M"+(-y);
}
return "http://online3.map.bdimg.com/onlinelabel/?qt=tile&x="+x+"&y="+y+"&z="+z+"&styles=pl&udt=20151021&scaler=1&p=1";
}
});
高德地图
source: new ol.source.XYZ({
url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}'
})
谷歌地图
source: new ol.source.XYZ({
url:'http://www.google.cn/maps/vt?lyrs=t@189&gl=cn&x={x}&y={y}&z={z}'
// url: 'http://www.google.cn/maps/vt/pb=!1m4!1m3!1i{z}!2i{x}!3i{y}!2m3!1e0!2sm!3i380072576!3m8!2szh-CN!3scn!5e1105!12m4!1e68!2m2!1sset!2sRoadmap!4e0!5m1!1e0'
// url:'http://mt0.google.cn/maps/vt?lyrs=s@773&gl=cn&x={x}&y={y}&z={z}'
// url:'http://www.google.cn/maps/vt?lyrs=m@189&gl=cn&x={x}&y={y}&z={z}'
// url:'http://www.google.cn/maps/vt?lyrs=s@189&gl=cn&x={x}&y={y}&z={z}'
// url:'http://www.google.cn/maps/vt?lyrs=h@189&gl=cn&x={x}&y={y}&z={z}'
})
天地图
new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'https://t0.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=天地图密钥',
}),
isGroup: true,
name: '天地图路网'
}),
new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'https://t0.tianditu.gov.cn/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=天地图密钥'
}),
图形绘制
图形交互绘制原理
图形表现的内容十分丰富,有基本的几何图形,即点、线、圆、矩形、多边形等;也有方向图形,即各种各样的方向箭头;还有标识某一内容的图形,如指北针、小旗子等。
交互式图形绘制的原理:先初始化一个矢量地图对象并添加到地图容器,然后加载交互式图形绘制控件,最后通过交互式图形控件在地图上绘制相应的几何图形,也可以通过交互式编辑控件来修改已经绘制好的几何图形。其中,在绘制几何图形时,可以根据需求设置不同的图形样式。在openLayers中,矢量地图为ol.layer.Vector,交互式图形绘制控件为ol.interaction.Draw,交互式编辑控件为ol.interaction.Modify,另外,在进行在编辑时,通常需要先选择某个目标,openLayers提供的选择要素控件为ol.interaction.Select。
图形绘制
除了点、线、圆、多边形直接可以设置类型,其它(正方形、长方形)需要自行编写,在设置绘图类型,代码如下:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="../css/ol.css" type="text/css">
<script type="text/javascript" src="../javascript/ol.js"></script>
<script type="text/javascript" src="../javascript/jquery-3.4.1.min.js"></script>
<style type="text/css">
#map {
width: 100%;
height: 90%;
position: absolute;
}
</style>
</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: 3
})
});
var typeSelect = document.getElementById('type'); //绘制类型选择对象
var draw; //ol.Interaction.Draw类的对象
//实例化一个矢量图层Vector作为绘制层
var source = new ol.source.Vector();
var vectorLayer = 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(vectorLayer);
//用户更改绘制类型触发的事件
typeSelect.onchange = function(e){
map.removeInteraction(draw); //移除绘制图形控件
addInteraction(); //添加绘制图形控件
};
function addInteraction(){
var typeValue = typeSelect.value; //绘制类型
if(typeValue !== 'None'){
var geometryFunction, maxPoints;
if(typeValue === 'Square'){ //正方形
typeValue = 'Circle'; //设置绘制类型为Circle
//设置几何信息变更函数,即创建正方形
geometryFunction = ol.interaction.Draw.createRegularPolygon(4);
}else if(typeValue === 'Box'){ //长方形
typeValue = '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;
};
}
console.log(typeValue);
//实例化图形绘制控件对象并添加到地图容器中
draw = new ol.interaction.Draw({
source: source,
type: typeValue, //几何图形类型
geometryFunction: geometryFunction, //几何信息变更时的回调函数
maxPoints: maxPoints //最大点数
});
map.addInteraction(draw);
}else{
//清空绘制的图形
source = null;
vector.setSource(source);
}
}
</script>
</body>
</html>
图形交互编辑
提到交互编辑不就要先对几何图形要素进行绘制,如何添加编辑几何图形要素呢,如下所示
//绘制的几何图形要素
var pointFeature = new ol.Feature(new ol.geom.Point([117.192, 39.878]));
var lineFeature = new ol.Feature(new ol.geom.LineString([[117.192, 39.878], [117.142, 39.858]]));
var polygonFeature = new ol.Feature(
new ol.geom.Polygon([[[117.172, 39.878], [117.132, 39.878], [117.152, 39.888], [117.182, 39.838], [117.192, 39.858]]])
);
//实例化一个矢量图层Vector作为绘制层
var source = new ol.source.Vector({
features: [pointFeature, lineFeature, polygonFeature]
});
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); //将绘制层添加到地图容器中
在地图中容器中创建一个交互式编辑控件需要使用ol.interaction.Modify来实现几何编辑功能。在此,综合选择要素控件(ol.interaction.Select)实现,选中要素后进行编辑功能操作
//定义修改几何图形的功能控件
var Modify = {
init: function(){
//初始化一个交互选择控件,并添加到地图容器中
this.select = new ol.interaction.Select();
map.addInteraction(this.select);
//初始化一个交互编辑控件,并添加到地图容器中
this.modify = new ol.interaction.Modify({
features: this.select.getFeatures() //选中的要素集
});
map.addInteraction(this.modify);
//设置激活状态变更的处理
this.setEvents();
},
setEvents: function(){
var selectedFeatures = this.select.getFeatures(); //选中的要素集
//添加选中要素变更事件
this.select.on("change:active", function(){
//遍历选择要素集,返回当前第一个要素(即移除的要素)
selectedFeatures.forEach(selectedFeatures.remove, selectedFeatures);
});
},
setActive: function(active){
this.select.setActive(active); //激活选择要素控件
this.modify.setActive(active); //激活修改要素控件
}
};
Modify.init(); //初始化几何图形修改控件
Modify.setActive(true); //激活几何图形修改控件
说明:为实现选中要素后编辑几何图形的功能,封装了一个Modify控件,分别实现初始化init方法,设置事件的setEvents方法、设置是否激活控件的setActive方法。在调用时先调用Modify的init方法进行初始化,然后调用setActive方法激活控件。
1 init:在初始化时首先加载交互选择要素的控件(ol.interaction.Select),然后加载一个交互编辑控件(ol.interaction.Modify),在实例化交互编辑控件时设置修改的features为当前选中的要素,最后调用setEvents方法进行选择控件激活状态变更的处理。
2 setEvents:在此方法中为当前选择控件添加激活变更事件,在其事件处理函数中返回当前选择要素集的第一个要素。
3 setActive: 在此方法中分别调用选择控件和编辑控件的setActive方法,对这两个控件的是否激活状态进行控制。
以上内容参考WebGIS之openLayers全面解析书籍