openlayers基础知识和常规操作 您所在的位置:网站首页 mystyle图片 openlayers基础知识和常规操作

openlayers基础知识和常规操作

2023-12-09 10:47| 来源: 网络整理| 查看: 265

官网地址:openlayers.org/ 中文相关资料链接和参考资料:

blog.csdn.net/qingyafan?t… linwei.xyz/ol3-primer/… 快速开始 引入openlayers相关资源 创建一个作为地图容器 使用JavaScript创建一个简单的地图 .map { height: 400px; width: 100%; } OpenLayers example My Map var map = new ol.Map({ //target参数是地图容器的id target: 'map', //layers设置图层 layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], //view设置地图中心点,缩放级别,分辨率和旋转 view: new ol.View({ center: ol.proj.fromLonLat([37.41, 8.82]), zoom: 4 }) }); 常用类简介 Layer 类

layer 是各种图层的基类,只用于让子类型继承和实现,一般自身不会实例化。主要有 WebGLPoints Layer、热力图(HeatMap Layer)、图片图层(Image Layer)、切片图层(Tile Layer) 和 矢量图层(Vector Layer) 五种类型。主要功能是对矢量数据和栅格数据的可视化。图层渲染结果的样式,主要与数据渲染方式有关,与数据源关系不大。

属性 source,指定了图层的数据来源,图层作用是以一定的样式渲染数据,source则指定了数据; className,图层各个元素的样式; opacity,透明度,默认为 1 ,即完全透明; visible,是否可见; zIndex,图层的叠加次序,默认是0,最底层,如果使用setMap方法添加的图层,zIndex值是Infinity,在最上层; extent,图层渲染的区域,即浏览器窗口中可见的地图区域。extent 是一个矩形范围,格式是[number, number, number, number] 分别代表 [left, bottom, right, top] 。为了提升渲染效率和加载速度,extent范围之外的瓦片是不会请求的,当然也不会渲染; minResolution,图层可见的最小分辨率; maxResolution,图层可见的最大分辨率; minZoom,图层可见的最小zoom level; maxZoom,图层可见的最大zoom level; 事件触发 postrender ( module:ol/render/Event~RenderEvent ) - 渲染图层后触发。 prerender ( module:ol/render/Event~RenderEvent ) - 在渲染层之前触发。 propertychange ( module:ol/Object.ObjectEvent ) - 更改属性时触发。 行为 各种类型的图层

openlayers的图层主要分为两类:Vector(矢量)和Raster(栅格),矢量图层是指在渲染发生在浏览器的图层,source返回的数据类型是矢量,如geojson的坐标串;栅格图层则是由服务器渲染,返回到浏览器的是一张张的瓦片图片,栅格图层主要是展示。 矢量图层类型有:

Graticule,地图上覆盖的网格标尺图层; HeatMap,热力图; Vector,矢量图 VectorImage,单张的矢量图层 VectorTile,矢量瓦片图层 WebGLPoints,WebGL渲染的海量点图层

栅格图层类型较为简单,只有Tile图层。 各种图层详细介绍: WebGLPoint Layer:对于海量数据的个性化渲染也成为了可能,WebGLPoint Layer的style也变成了一个非常实用的功能。 Heatmap Layer:将矢量数据渲染成热度图的类,继承了 ol.layer.Vector 类,ol.layer.Vector 继承了ol.layer.Layer 类, 额外的参数是 olx.layer.HeatmapOptions blur 控制圆点的边缘,对边缘做模糊化; radius 则规定了圆点的半径

var heatmap = new ol.layer.Heatmap({ source: new ol.source.KML({ url: 'data/kml/2012_Earthquakes_Mag5.kml', projection: 'EPSG:3857', extractStyles: false }), blur: parseInt(blur.value, 10), radius: parseInt(radius.value, 10) }); map = new ol.Map({ //初始化map target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.MapQuest({layer: 'sat'}) }), heatmap ], view: new ol.View({ center: ol.proj.transform([37.41, 8.82], 'EPSG:4326', 'EPSG:3857'), zoom: 4 }) });

Image Layer:主要是指服务器端渲染的图像,可能是已经渲染好的图像,或者是每一次请求,都根据请求内容定制化地生成一幅图片,该图层类型支持任意的范围和分辨率。

var imageLayer = new ol.layer.Image({ source: new ol.source.ImageStatic({ url: 'sample.jpg', projection: projection, imageExtent: extent }) }) map = new ol.Map({ //初始化map target: 'map', layers: [ imageLayer ], view: new ol.View({ projection: projection, center: ol.extent.getCenter(extent), zoom: 2 }) });

Tile Layer:切片地图是比较常用的图层类型,切片的概念,就是利用网格将一幅地图切成大小相等的小正方形 Vector Layer:即矢量图层,矢量图层实际上是在客户端渲染的图层类型,服务器返回的数据或者文件会通过 OpenLayers 进行渲染,得到相应的矢量图层。vectorlayer 相对于其他类型的图层,还包含了一个 style 参数,这个参数便是控制矢量图层的外观样式的,style 是一个 ol.style.Style 类型。

vectorLayer = new ol.layer.Vector({ //初始化矢量图层 source: new ol.source.GeoJSON({ projection: 'EPSG:3857', url: 'data/geojson/countries.geojson' //从文件加载边界等地理信息 }), style: function(feature, resolution) { style.getText().setText(resolution < 5000 ? feature.get('name') : ''); //当放大到1:5000分辨率时,显示国家名字 return [style]; } }); Source

source 是 Layer 的重要组成部分,表示图层的来源,也就是服务地址。除了在构造函数中制定外,可以使用 layer.setSource(source) 稍后指定。 source 是 layer 中必须的选项,定义着地图数据的来源,与数据有关的函数,如addfeature、getfeature等函数都定义在 source 中,而且数据源支持多种格式。

类型: ol.source.Vector:矢量图层的数据来源 ol.source.Tile:提供被切分为切片的图片地图数据 ol.source.Image:提供单一的图片地图

以下介绍主要基于ol.source.Vector

用法说明

包含四个事件,addfeature,changefeature,clear,removefeature。

addfeature,当一个要素添加到 source 中触发; changefeature,当要素变化时触发; clear,当 source 的 clear 方法调用时候触发; removefeature,当要素移除时候发生。 参数 attribution,地图右下角的 logo 包含的内容; features,地理要素,从字符串读取的数据; format,url属性设置后,加载要素使用的数据格式,采用异步的 AJAX 加载; loader,加载要素使用的加载函数; logo,logo包含的内容; strategy,加载要素使用的策略,默认是 一次性加载所有要素; url,要素数据的地址; wrapX,是否在地图水平坐标轴上重复,默认是 true。 方法

features 方法:假如有一个包含空间数据的字符串,geojsonObject,是GeoJSON字符串格式,那么可以用来初始化一个图层。

var vectorSource = new ol.source.Vector({ features: (new ol.format.GeoJSON()).readFeatures(geojsonObject) }); var vectorLayer = new ol.layer.Vector({ source: vectorSource, style: style }); map.addLayer(vectorLayer);

url + format 方法:如果有一个文件作为数据源,那么可以配置 url 属性来加载数据

var vectorLayer = new ol.layer.Vector({ source: new ol.source.Vector({ url: 'data/geojson/countries.geojson', format: new ol.format.GeoJSON() }) });

这两种方法中都会指定数据来源格式, 矢量数据源支持的格式包含很多:gml、EsriJSON、geojson、gpx、igc、kml、osmxml、ows、polyline、topojson、wfs、wkt、wms capabilities(兼容 wms 的格式)、 wms getfeatureinfo、 wmts capabilities、xlink、xsd等格式。这些格式都有**readFeatures **、**readFeature 和readGeometry **方法用于读取数据。

interaction

地图的交互功能包含很多,如地图双击放大,鼠标滚轮缩放,矢量要素点选,地图上绘制图形等等。只要是涉及到与地图的交互,就会涉及到 intercation 类,它定义了用户与地图进行交互的基本要素和事件。

属性 doubleclickzoom interaction,双击放大交互功能; draganddrop interaction,以“拖文件到地图中”的交互添加图层; dragbox interaction,拉框,用于划定一个矩形范围,常用于放大地图; dragpan interaction,拖拽平移地图; dragrotateandzoom interaction,拖拽方式进行缩放和旋转地图; dragrotate interaction,拖拽方式旋转地图; dragzoom interaction,拖拽方式缩放地图; draw interaction,绘制地理要素功能; interaction defaults ,规定了默认添加的交互功能; keyboardpan interaction,键盘方式平移地图; keyboardzoom interaction,键盘方式缩放地图; select interaction,选择要素功能; modify interaction,更改要素; mousewheelzoom interaction,鼠标滚轮缩放功能; pinchrotate interaction,手指旋转地图,针对触摸屏; pinchzoom interaction,手指进行缩放,针对触摸屏; pointer interaction,鼠标的用户自定义事件基类; snap interaction,鼠标捕捉,当鼠标距离某个要素一定距离之内,自动吸附到要素。 交互

interaction defaults - 默认添加的交互功能 默认添加的交互包括: DragRotate, DragZoom, DoubleClickZoom, PinchRotate, PinchZoom, DragPan, KeyboardZoom, KeyboardPan, MouseWheelZoom

//去除某个默认项 interactions: ol.interaction.defaults([ doubleClickZoom: false ]),

draw interaction - 绘图功能 绘图交互允许绘制几何地理要素,可选参数为一个对象,包含以下属性。

features,绘制的要素的目标集合; source,绘制的要素的目标图层来源,即目标图层的 source属性 ; snapTolerance,自动吸附完成点的像素距离,也就是说当鼠标位置距离闭合点小于该值设置的时候,会自动吸附到闭合点,默认值是 12; type,绘制的地理要素类型,ol.geom.GeometryType类型,包含 Point、 LineString、 Polygon、MultiPoint、MultiLineString 或者 MultiPolygon; minPointsPerRing,绘制一个多边形需要的点数最小值,数值类型,默认是 3; style,要素素描的样式,是 ol.style.Style对象之一; geometryName,绘制的地理要素的名称,string类型; condition,一个函数,接受一个ol.MapBrowserEvent类型的参数,返回一个布尔值表示是否应该调用事件处理函数。默认情况下,增加一个顶点,类型为 ol.events.ConditionType。 //给地图添加该交互功能,首先需要实例化一个ol.interaction.Draw,必须指定 source和type属性 var draw = new ol.interaction.Draw({ source: source, type: "Polygon" }); //然后将该功能添加到地图中。 map.addInteraction(draw)

dragrotateandzoom interaction - 鼠标拖拽进行缩放和旋转地图

var interactions = ol.interaction.defaults().extend([ new ol.interaction.DragRotateAndZoom() ]); var map = new ol.Map({ ... interactions:interactions, ... })

dragbox interaction - 拉框交互 draganddrop interaction - 拖拽文件到地图 将空间数据使用鼠标或者手指拖拽到地图中,解析成一个图层添加到地图中。目前只支持矢量数据,未来可能支持更多的空间数据格式。目前,支持的格式包括 GeoJSON, GML, KML, GPX, OSMXML, TopoJSON 和 IGC。

var dragAndDropInteraction = new ol.interaction.DragAndDrop({ formatConstructors: [ ol.format.GeoJSON, ol.format.KML ] }); var interactions = ol.interaction.defaults().extend([ new ol.interaction.DragRotateAndZoom(), dragAndDropInteraction ]);

keyboard interaction - 键盘交互功能 modify 和 select interaction select 就像名字暗示的一样,是用来选中要素的;而 modify 是修改要素的,主要是通过拖拽方式修改点的坐标。

//模拟选中并修改要素的交互功能需要添加如下代码 var select = new ol.interaction.Select(); var moddify = new ol.interaction.Modify({ features:select.getFeatures() });

pinchrotate ,pinchzoom interaction - 两个手指缩放和旋转地图 pointer interaction - 自定义鼠标事件 针对鼠标的行为按下(Down)、移动(Move)和抬起(Up),自定义事件。这三个事件发生有先后顺序,首先是触发按下,之后是移动事件,最后是抬起事件。只要配置相关的属性,包含handleDownEvent,handleDragEvent,handleMoveEvent,handleUpEvent分别对应鼠标的 down、drag、move和up四种事件。

new ol.interaction.Pointer({ handleDownEvent: functionName })

snap interaction - 鼠标捕捉 当修改和绘制矢量要素时,鼠标距离某个要素一定距离之内,自动吸附到要素。

control类(地图控件) 控件

OpenLayers 中包含的控件有:

controldefaults,地图默认包含的控件,包含缩放控件和旋转控件; fullscreencontrol,全屏控件,用于全屏幕查看地图; mousepositioncontrol,鼠标位置控件,显示鼠标所在地图位置的坐标,可以自定义投影; overviewmapcontrol,地图全局视图控件; rotatecontrol,地图旋转控件; scalelinecontrol,比例尺控件; zoomcontrol,缩放控件; zoomslidercontrol,缩放刻度控件; zoomtoextentcontrol,缩放到全局控件。 方法

调整控件样式的两种方法: 1.** 修改控件的可选参数的默认值**

.mouse-position-wrapper{ width:300px; height:29px; color:#FFFFFF; position:absolute; right:20px; bottom:6px; z-index:999; } //调整控件位置 controls: ol.control.defaults().extend([ new ol.control.FullScreen(), new ol.control.MousePosition({ coordinateFormat: ol.coordinate.createStringXY(4), projection: 'EPSG:4326', className: 'custom-mouse-position', target: document.getElementById('mouse-position') }) ]),

2.覆盖默认样式- 在自己的 CSS 样式表中添加如下代码(因为自己的CSS文件样式优先级比外部链接引入的样式优先级高)

/* rewrite the default css in `ol.css` */ .ol-rotate{ right:40px; } View

初始化一幅地图,必备的三要素之一就是视图(view),这个对象主要是控制地图与人的交互,如进行缩放,调节分辨率、地图的旋转等控制。

属性 view 的构造函数需要的参数是一个 olx.ViewOptions对象,主要属性如下: center 是一个坐标[x, y],表示地图视图的中心位置; extent 是一个数组对象 – [left, bottom, right, top],表示地图视图的初始范围; projection 是地图的投影坐标系统; resolution 表示地图的分辨率,单位并不是普通的单位面积的像素,而是单位像素表示的距离单位,比如 米/像素; rotation 表示地图的旋转角度; zoom 表示地图初始的缩放级别。 style

地图样式是由 style 类控制的,其包含了地图样式的方方面面,例如,填充色、图标样式、图片样式、规则图形样式、边界样式、文字样式等,样式一般针对矢量要素图层。 矢量图层样式可以事先写好,写成静态的,矢量图层直接按照定义好的样式渲染,也可以动态使用样式的 set() 方法,但是要注意刷新矢量图层,重新渲染,否则动态样式不生效。 样式主要针对矢量图层数据,既可以配置一个全局的样式,也可以针对每个feature单独配置;既可以应用统一的样式,也可以根据要素和分辨率应用条件样式。样式应用是非常灵活的。

配置项 geometry,要素的属性,或者要素,或者一个返回一个地理要素的函数,用来渲染成相应的地理要素;

一般与 image 样式配合使用,表示 image 放置的位置

//该样式配置了一个 image 属性,表示在相应的位置放置的图片的样式, //这里是一个半径为 5,填充色为橙色的圆形的图片样式 new ol.style.Style({ image: new ol.style.Circle({ radius: 5, fill: new ol.style.Fill({ color: 'orange' }) }), geometry: function(feature) { // return the coordinates of the first ring of the polygon var coordinates = feature.getGeometry().getCoordinates()[0]; return new ol.geom.MultiPoint(coordinates); } }) fill,填充要素的样式;

配置图层的要素的填充颜色和透明度

iamge,图片样式,类型为 ol.style.Image;

样式主要针对矢量图层(vector layer),矢量图层中包含一个或多个要素(feature),要素中包含一个地理属性(geometry)表示地理位置,还可能包含一个或多个其他属性,比如要素的名称、类型等等,要素可以使用单独的样式,这时候要使用 feature.setStyle(ol.style.Style) 来设置单独使用的样式,否则直接继承矢量图层的样式

//定义一个图标样式 var iconStyle = new ol.style.Style({ image: new ol.style.Icon(({ src: 'data/icon.png' })) }); //定义一个点要素 var iconFeature = new ol.Feature({ geometry: new ol.geom.Point([0, 0]), }); //将样式应用于点要素 iconFeature.setStyle(iconStyle); //定义一个矢量图层,并加入该要素 var iconLayer = new ol.layer.Vector({ source: new ol.source.Vector({ features: [iconFeature] }) }); stroke,要素边界样式,类型为 ol.style.Stroke; color: '#319FD3', width: 1 text,要素文字的样式,类型为 ol.style.Text; text: new ol.style.Text({ font: '12px Calibri,sans-serif', //字体与大小 fill: new ol.style.Fill({ //文字填充色 color: '#000' }), stroke: new ol.style.Stroke({ //文字边界宽度与颜色 color: '#fff', width: 3 }) }) zIndex,CSS中的zIndex,即叠置的层次,为数字类型。 子类 ol.style.Circle,针对矢量要素设置圆形的样式,继承 ol.style.Image; ol.style.Icon,针对矢量数据设置图标样式,继承 ol.style.Image; ol.style.Fill,针对矢量要素设置填充样式; ol.style.RegularShape,对矢量要素设置规则的图形样式,如果设置 radius,结果图形是一个规则的多边形,如果设置 radius1 和 radius2,结果图形将是一个星形; ol.style.Stroke,矢量要素的边界样式; ol.style.Text,矢量要素的文字样式。 var style = new ol.style.Style({ fill: new ol.style.Fill({ //矢量图层填充颜色,以及透明度 color: 'rgba(255, 255, 255, 0.6)' }), stroke: new ol.style.Stroke({ //边界样式 color: '#319FD3', width: 1 }), text: new ol.style.Text({ //文本样式 font: '12px Calibri,sans-serif', fill: new ol.style.Fill({ color: '#000' }), stroke: new ol.style.Stroke({ color: '#fff', width: 3 }) }) });

条件样式

条件样式是将样式配置为一个回调函数,其参数包含要素本身和分辨率,可以根据要素本身的属性和地图的分辨率,显示动态的样式,形式如 style: function(feature, resolution) {}。 例如,以下代码段配置当分辨率小于 5000 时候,在要素上显示一个标签,标识要素名称:

style: function(feature, resolution) { style.getText().setText(resolution < 5000 ? feature.get('name') : ''); return styles; } Vector 在 GIS 中,地图一般分为两大类:栅格地图和矢量地图,栅格地图其实就是数码照片,只不过有的是卫星拍的。它们有一个共同特征,就是它们都是由很多个像素组成,像素大小是一致的,行高和列宽是一致的,从这个角度看,一幅遥感影像就像栅格。 矢量地图,是由很多要素组成的,每个要素都有自己的地理坐标,基于数学规则,无论矢量地图怎么放大,地图都不会失真。它是 OpenLayers 中非常重要的一种图层类型,利用矢量地图可以实现非常多的功能,如 动态标绘、调用 WFS 服务、编辑要素、可点击的要素、动态加载要素 等等。

矢量图层是在客户端渲染的,在 web 环境中,对应的就是浏览器。构成一个矢量图层的包含一个数据(source)和一个样式(style),数据构成矢量图层的要素,样式规定要素显示的方式和外观。一个初始化成功的矢量图层包含一个到多个要素(feature),每个要素由地理属性(geometry)和多个其他的属性,可能包含名称等。结构如下图:

属性

在初始化矢量图层时,可以有很多选项配置矢量图层的行为和外观,常用的有:

brightness、contrast,图层亮度和对比度,都是一个数值; renderOrder,一个指定规则的函数 (function(ol.Feature, ol.Feature)); hue,色调,是一个数值; minResolution,可见的最小分辨率; maxResolution,可见的最大分辨率; opacity,图层的透明度,0~1之间的数值,1表示不透明; saturation,饱和度; source,图层数据来源; style,图层样式,一个ol.style.Style或者一个ol.style.Style数组,或者一个返回 ol.style.Style 的函数; visible,图层可见性,默认为 true。 //初始化一个矢量图层 var vector = new ol.layer.Vector({ source: new ol.source.Vector({ url: 'data/china_province_boundries.geojson', //数据来源 projection: 'EPSG:3857', //数据解析器 因为 url 规定的数据来源是 geojson 格式,所以解析器也是 geojson 解析器 new ol.format.GeoJSON format: new ol.format.GeoJSON({ extractStyles: false }) }), style: style }); 方法

取得要素 vector 的数据包含在 source 中,要取得 vector 的 feature 数据,要在 source 中,例如 vector.getSource().getFeatures(),该函数会返回一个 feature array,直接使用 [ ],取用即可,或者根据要素的 ID 取得(getFeatureById())。 取得要素的 geometry 利用 getGeometry() 可以获得要素的地理属性,这个函数当然返回要素包含的 geometry,geometry 包含很多类型,主要有 point、multi point、linear ring、line string、multi line string、polygon、multi polygon、circle。 取得 geometry 后,就可以获得要素的坐标了,可以根据坐标做一些地理判断,比如判断 一个坐标是否位于要素内(containsCoordinate(coordinate) 或者 containsXY(x, y)),取得要素的中心坐标等。

Overlay(覆盖物)

主要的用途就是在地图之上再覆盖一层,用以显示额外的可见元素,可见元素一般是 HTML 元素,利用 overlay,可以将可见元素放置到地图的任意位置,形成地图上再浮动一层的效果。例如在地图上相应的坐标放置一个标志,标签,利用 overlay 都可以做到,具体来说,点击地图上某位置,在点击位置弹出弹出框就是利用了 overlay。

配置项 id,为对应的 overlay 设置一个 id,便于使用 ol.Map 的 getOverlayById 方法取得相应的 overlay; element,overlay 包含的 DOM element; offset,偏移量,像素为单位,overlay 相对于放置位置(position)的偏移量,默认值是 [0, 0],正值分别向右和向下偏移; position,在地图所在的坐标系框架下,overlay 放置的位置; positioning,overlay 对于 position 的相对位置,可能的值包括 bottom-left、bottom-center、bottom-right 、center-left、center-center、center-right、top-left、top-center、top-right,默认是 top-left,也就是 element 左上角与 position 重合; stopEvent,地图的事件传播是否停止,默认是 true,即阻止传播,可能不太好理解,举个例子,当鼠标滚轮在地图上滚动时,会触发地图缩放事件,如果在 overlay 之上滚动滚轮,并不会触发缩放事件,如果想鼠标在 overlay 之上也支持缩放,那么将该属性设置为 false 即可; insertFirst,overlay 是否应该先添加到其所在的容器(container),当 stopEvent 设置为 true 时,overlay 和 openlayers 的控件(controls)是放于一个容器的,此时将 insertFirst 设置为 true ,overlay 会首先添加到容器,这样,overlay 默认在控件的下一层(CSS z-index),所以,当 stopEvent 和 insertFirst 都采用默认值时,overlay 默认在 控件的下一层; autoPan,当触发 overlay setPosition 方法时触发,当 overlay 超出地图边界时,地图自动移动,以保证 overlay 全部可见; autoPanAnimation,设置 autoPan 的效果动画,参数类型是 olx.animation.panOptions; autoPanMargin,地图自动平移时,地图边缘与 overlay 的留白(空隙),单位是像素,默认是 20像素; 事件 change,当引用计数器增加时,触发; change:element,overlay 对应的 element 变化时触发; change:map,overlay 对应的 map 变化时触发; change:offset,overlay 对应的 offset 变化时触发; change:position,overlay 对应的 position 变化时触发; change:positioning,overlay 对应的 positioning 变化时触发; propertychange,overlay 对应的属性变化时触发; // example overlay event binding var overlay = new ol.Overlay({ // ... }); overlay.on("change:position", function(){ console.log("位置改变!"); }) 方法 getElement,取得包含 overlay 的 DOM 元素; getId,取得 overlay 的 id; getMap,获取与 overlay 关联的 map对象; getOffset,获取 offset 属性; getPosition,获取 position 属性; getPositioning,获取 positioning 属性; setElement;设置 overlay 的 element; setMap,设置与 overlay 的 map 对象; setOffset,设置 offset; setPosition,设置 position 属性; setPositioning,设置 positioning 属性。 常用操作 加载天地图底图 // 背景 let tian_di_tu_road_layer = new ol.layer.Tile({ title: "天地图路网", source: new ol.source.XYZ({ url: "http://t4.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=xxx" }) }); // 文字标注 let tian_di_tu_annotation = new ol.layer.Tile({ title: "天地图文字标注", source: new ol.source.XYZ({ url: 'http://t4.tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=xxx' }) }); // 地图创建 let map = new ol.Map({ ... // 图层 layers: [tian_di_tu_road_layer, tian_di_tu_annotation], ... }); 加载 WFS 服务

WFS服务,可以通过OL进行加载,加载有简单方式也有GetFeature方式,该种方式自由度更大,可以结合一些过滤条件,这样一方面可以提高加载数据的效率。

一次性加载数据 // WFS 格式化工具 const wfsJsonFormat = new ol.format.WFS(); // GML 格式化工具 const gmlJsonFormat = new ol.format.GML(); // 矢量数据源 const vectorSource = new ol.source.Vector(); // 创建一个请求 const featureRequest = wfsJsonFormat.writeGetFeature({ srsName: 'EPSG:4326',//坐标系 featureNS: url, // 注意这个值必须为创建工作区时的命名空间URI featurePrefix: 'XXX_LAYER', //工作区的名称 featureTypes: ['PUMP_GATE_STATION_POINT'], //所要访问的图层 outputFormat: 'application/json' //这里面有三个参数是必须的:featureNS、featurePrefix、featureTypes。这三个参数必须赋值否则错误。 }); // 利用 XMLSerializer.serializeToString 将 xml 格式转为 string //let xmlSerializer = new XMLSerializer(); //let params = xmlSerializer.serializeToString(featureRequest); // 发起请求 fetch(url, { method: 'POST', body: new XMLSerializer().serializeToString(featureRequest) }).then(response => { // xml 格式不能直接用 response.json() 转 return response.text(); //非xml格式 //return response.json(); }).then(data => { // 读取图形信息 let features = gmlJsonFormat.readFeatures(data); //非xml格式 //var features = new ol.format.GeoJSON().readFeatures(json); if (features.length > 0) { // 添加图形 vectorSource.addFeatures(features); // 调整地图视角 map.getView().fit(vectorSource.getExtent()); } }) // 矢量图层 const layer = new ol.layer.Vector({ // 设置数据源 source: vectorSource, // 设置图层样式 style: new ol.style.Style({ image: new ol.style.Icon({ scale: 0.8, src: require("imgurl") }) }) }); // 将图层添加到地图上 map.addLayer(layer); 动态加载数据 // 矢量数据源 const vectorSource = new VectorSource({ // 设置格式化类型 format: new ol.format.GeoJSON(), // url(extent) 在地图范围变化时调用,返回当前的地图范围 url: function (extent) { return ( `url?service=WFS&version=1.0.0&request=GetFeature&typeName=luhao%3Asuqian&maxFeatures=50&outputFormat=application%2Fjson&bbox=${extent.join(',')},EPSG:4326` ); }, strategy: ol.loadingstrategy.bbox }); // 矢量图层 const layer = new ol.layer.Vector({ // 设置数据源 source: vectorSource, // 设置图层样式也可以 function (feature) { /** 根据内容动态加载样式 **/ return Style} style: new ol.style.Style({ image: new ol.style.Icon({ scale: 0.8, src: require("imgurl") }) }) }); // 将图层添加到地图上 map.addLayer(layer); 加载 geoService 服务 一次性加载数据 // GeoJSON 格式化工具 const geoJsonFormat = new ol.format.GeoJSON(); // 矢量数据源 const vectorSource = new ol.source.Vector(); // 请求参数 let params = { service: "WFS", version: "1.0.0", request: "GetFeature", typeName: "name", maxFeatures: "50", outputFormat: "application/json", } // 发起请求 request({url: 'url', params}).then(response => { // 读取图形数据 const features = geoJsonFormat.readFeatures(response); if (features.length > 0) { // 添加图形 vectorSource.addFeatures(features); // 调整地图视角 map.getView().fit(vectorSource.getExtent()); } }); // 矢量图层 const layer = new ol.layer.Vector({ // 设置数据源 source: vectorSource, // 设置图层样式也可以 function (feature) { /** 根据内容动态加载样式 **/ return Style} style: new ol.style.Style({ image: new ol.style.Icon({ scale: 0.8, src: require("imgurl") }) }) }); // 将图层添加到地图上 map.addLayer(layer); 动态加载数据 // 矢量数据源 const vectorSource = new ol.source.Vector({ // 设置格式化类型 format: new ol.format.GeoJSON(), // url(extent) 在地图范围变化时调用,返回当前的地图范围 url: function (extent) { return 'url?service=WFS&version=1.0.0&request=GetFeature&typeName=luhao%3Asuqian&maxFeatures=50&outputFormat=application%2Fjson&' + 'bbox=' + extent.join(',') + ',EPSG:4326'; }, strategy: ol.loadingstrategy.bbox, }); // 矢量图层 const layer = new ol.layer.Vector({ // 设置数据源 source: vectorSource, // 设置图层样式也可以 function (feature) { /** 根据内容动态加载样式 **/ return Style} style: new ol.style.Style({ image: new ol.style.Icon({ scale: 0.8, src: require("imgurl") }) }) }); // 将图层添加到地图上 map.addLayer(layer); 加载 arcgis 服务 一次性加载数据 // EsriJSON 格式化工具 const esriJsonFormat = new ol.format.EsriJSON(); // 矢量数据源 const vectorSource = new ol.source.Vector(); // 请求参数 let params = { f: 'json', where: '1=1', returnGeometry: true, spatialRel: 'esriSpatialRelIntersects', inSR: 4326, outSR: 4326, outFields: '*', }; // 发起请求 request({url: 'url', params}).then(response => { // 读取图形数据 const features = esriJsonFormat.readFeatures(response); if (features.length > 0) { // 添加图形 vectorSource.addFeatures(features); // 调整地图视角 map.getView().fit(vectorSource.getExtent()); } }); // 唯一值渲染 let {Style, Icon} = ol.style; const styleCache = { '流量': new Style({ image: new Icon({ scale: 0.8, src: require("imgurl") }) }), '雨量': new Style({ image: new Icon({ scale: 0.8, src: require("imgurl") }) }), '水位': new Style({ image: new Icon({ scale: 0.8, src: require("imgurl") }) }) }; // 矢量图层 const layer = new ol.layer.Vector({ // 设置数据源 source: vectorSource, // 设置图层样式 style: function (feature) { // 获取属性 MONITOR_TYPE 的值 const classify = feature.get('MONITOR_TYPE'); // 根据值动态渲染 return styleCache[classify]; } }); // 将图层添加到地图上 map.addLayer(layer); 动态加载数据 // 矢量数据源 const vectorSource = new ol.source.Vector({ loader: function (extent, resolution, projection, success, failure) { // 请求参数 let params = { f: 'json', where: '1=1', returnGeometry: true, spatialRel: 'esriSpatialRelIntersects', inSR: 4326, outSR: 4326, outFields: '*', geometryType: 'esriGeometryPolygon', geometry: encodeURIComponent( '{"xmin":' + extent[0] + ',"ymin":' + extent[1] + ',"xmax":' + extent[2] + ',"ymax":' + extent[3] + ',"spatialReference":{"wkid":4326}}' ) } // 发起请求 request({url: url, params}).then(response => { // 读取图形数据 const features = esriJsonFormat.readFeatures(response); if (features.length > 0) { // 添加图形 vectorSource.addFeatures(features); } }); }, strategy: ol.loadingstrategy.tileStrategy( createXYZ({ tileSize: 512, }) ), }); // 矢量图层 const layer = new ol.layer.Vector({ // 设置数据源 source: vectorSource, // 设置图层样式也可以 function (feature) { /** 根据内容动态加载样式 **/ return Style} style: new ol.style.Style({ image: new ol.style.Icon({ scale: 0.8, src: require(imgurl) }) }) }); // 将图层添加到地图上 map.addLayer(layer); 获取加载后的所有feature(注意异步) var vectorLayer = new ol.layer.Vector({ source: new ol.source.Vector({ url: '../data/geojson/line-samples.geojson', format: new ol.format.GeoJSON() }) }); // 因为是异步加载,所以要采用事件监听的方式来判定是否加载完成 var listenerKey = vectorLayer.getSource().on('change', function(){ // 判定是否加载完成 if (vectorLayer.getSource().getState() === 'ready') { document.getElementById('count').innerHTML = vectorLayer.getSource().getFeatures().length; // 注销监听器 vectorLayer.getSource().unByKey(listenerKey); } }); // map.addLayer(vectorLayer); 图层显示隐藏 //利用方法setVisible和setZIndex来控制图层,满足80%的这种需求 // 隐藏显示osm图层 function checkOsm(elem) { osmLayer.setVisible(elem.checked); } // 置顶osm图层到最上面 function upOsm (elem) { if (elem.checked) { osmLayer.setZIndex(3); circleLayer.setZIndex(circleLayer.getZIndex()-1); pointLayer.setZIndex(pointLayer.getZIndex()-1); } } 利用overlay加载图标 var anchor = new ol.Overlay({ element: document.getElementById('anchor') }); // 关键的一点,需要设置附加到地图上的位置 anchor.setPosition([104, 30]); // 然后添加到map上 map.addOverlay(anchor);

优点:可以直接对元素进行css处理

利用Featue + Style加载图标 // 我们需要一个vector的layer来放置图标 var layer = new ol.layer.Vector({ source: new ol.source.Vector() }) var map = new ol.Map({ layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), //把layer添加到layers layer ], target: 'map', view: new ol.View({ projection: 'EPSG:4326', center: [104, 30], zoom: 10 }) }); // 创建一个Feature,并设置好在地图上的位置 var anchor = new ol.Feature({ geometry: new ol.geom.Point([104, 30]) }); // 设置样式,在样式中就可以设置图标 anchor.setStyle(new ol.style.Style({ image: new ol.style.Icon({ src: '../img/anchor.png' }) })); // 添加到之前的创建的layer中去 可以理解为向layer的source中添加要素 layer.getSource().addFeature(anchor); 图标根据地图层级放大缩小 // 监听地图层级变化 map.getView().on('change:resolution', function(){ var style = anchor.getStyle(); // 重新设置图标的缩放率,基于层级10来做缩放 style.getImage().setScale(this.getZoom() / 10); anchor.setStyle(style); }) svg代替图片作为图标 // 构建svg的Image对象 var svg = ''+ ''+ ''; var mysvg = new Image(); mysvg.src = 'data:image/svg+xml,' + escape(svg); 创建规则几何图标 var shape = new ol.Feature({ geometry: new ol.geom.Point([104, 30]) }); // 添加一个三角形 shape.setStyle(new ol.style.Style({ image: new ol.style.RegularShape({ points: 3, // 顶点数 radius: 10, // 图形大小,单位为像素 stroke: new ol.style.Stroke({ // 设置边的样式 color: 'red', size: 2 }) }) })); layer.getSource().addFeature(shape); // 添加一个五星 ... star.setStyle(new ol.style.Style({ image: new ol.style.RegularShape({ points: 5, // 顶点个数 radius1: 20, // 外圈大小 radius2: 10, // 内圈大小 stroke: new ol.style.Stroke({ // 设置边的样式 color: 'red', size: 2 }), fill: new ol.style.Fill({ // 设置五星填充样式 color: 'blue' }) }) })); ... canvas自绘图标 // 使用canvas绘制一个不规则几何图形 var canvas =document.createElement('canvas'); canvas.width = 20; canvas.height = 20; var context = canvas.getContext("2d"); context.strokeStyle = "red"; context.lineWidth = 1; context.beginPath(); context.moveTo(0, 0); context.lineTo(20, 10); context.lineTo(0, 20); context.lineTo(10, 10); context.lineTo(0, 0); context.stroke(); // 把绘制了的canvas设置到style里面 var style = new ol.style.Style({ image: new ol.style.Icon({ //img属性设置具体样式,与svg相同 img: canvas, //必须设置imgSize imgSize: [canvas.width, canvas.height], rotation: 90 * Math.PI / 180 }) }); 动态改变图标 // 监听地图点击事件 map.on('click', function(event){ var feature = map.forEachFeatureAtPixel(event.pixel, function(feature){ return feature; }); if (feature) { // 将空心五星为红色实心五星 var style = feature.getStyle().getImage(); feature.setStyle(new ol.style.Style({ image: new ol.style.RegularShape({ points: 5, radius1: 20, radius2: 10, stroke: style.getStroke(), fill: new ol.style.Fill({ color: 'red' }) }) })); } }); 设置文字 var anchor = new ol.Feature({ geometry: new ol.geom.Point([104.06, 30.67]) }); // 设置文字style anchor.setStyle(new ol.style.Style({ text: new ol.style.Text({ // font: '10px sans-serif' 默认这个字体,可以修改成其他的,格式和css的字体设置一样 text: '这里是成都', fill: new ol.style.Fill({ color: 'red' }) }) })); layer.getSource().addFeature(anchor); style Function应用(根据层级放大缩小图标)

在feature上应用了styleFunction,通过官网API文档可以看到,其类型为ol.FeatureStyleFunction,函数仅带有一个参数resolution,在上面的代码中看到了,在函数体内this指的是当前的feature

var anchor = new ol.Feature({ geometry: new ol.geom.Point([104, 30]) }); // 应用style function,动态的获取样式 anchor.setStyle(function(resolution){ //这里需要返回一个数组!!! return [new ol.style.Style({ image: new ol.style.Icon({ src: '../img/anchor.png', scale: map.getView().getZoom() / 10 }) })]; }); layer.getSource().addFeature(anchor); layer style使用Function

该函数具有两个参数,第一个参数为feature,第二个参数为resolution,同样地,该函数需要返回style数组。

// 创建layer使用的style function,根据feature的自定义type,返回不同的样式 var layerStyleFunction = function(feature, resolution) { var type = feature.get('type'); var style = null; // 点 if (type === 'point') { style = new ol.style.Style({ image: new ol.style.Circle({ radius: 1, fill: new ol.style.Fill({ color: 'red' }) }) }); } else if ( type === 'circle') { // 圆形 ... } else { // 其他形状 style = new ol.style.Style({ ... } // 返回 style 数组 return [style]; }; var layer2 = new ol.layer.Vector({ source: new ol.source.Vector(), style: layerStyleFunction // 应用上面创建的 style function }); 大量图标方案

如果图标不进行交互,可以把图标渲染到底图上。

复用样式减少内存占用

在应用大量图标的时候,其实图标样式差异化并不大,比如快餐店,公共厕所,公交站点等等有很多,但都是用同样的图标在地图上标准,在不注意的时候,我们是采用下面的方式来添加图标的:

//for (var index = 0; index < 10000; index++) { // var feature = new ol.Feature({ // geometry: new ol.geom.Point([latlon[index].lon, latlon[index].lat]) // }); // feature.setStyle(new ol.style.Style({ // image: new ol.style.Icon({ // src: '../img/marker.png' // }) // })); //} //对每个feature设置style的时候,都是直接new的,这样势必会创建很多对象,占用很多内存 //优化 var styles = [ new ol.style.Style({ image: new ol.style.Icon({ src: '../img/marker1.png' }) }), new ol.style.Style({ image: new ol.style.Icon({ src: '../img/marker2.png' }) }), new ol.style.Style({ image: new ol.style.Icon({ src: '../img/marker3.png' }) }) ]; for (var index = 0; index < 10000; index++) { var feature = new ol.Feature({ geometry: new ol.geom.Point([latlon[index].lon, latlon[index].lat]) }); feature.setStyle(styles[index % styles.length]); } 复用Canvas提高效率

用一个大的canvas来绘制多个图标,这样就能减少canvas的数量,从而提高效率

提示信息 ...... // 获取到popup的节点 var container = document.getElementById('popup'); var content = document.getElementById('popup-content'); var closer = document.getElementById('popup-closer'); // 创建一个overlay, 绑定html元素container var overlay = new ol.Overlay(/** @type {olx.OverlayOptions} */ ({ element: container, autoPan: true, autoPanAnimation: { duration: 250 } })); ...... // 监听地图点击事件 map.on('singleclick', function(evt) { // 获取当前点击坐标,并设置到HTML元素上去 var coordinate = evt.coordinate; var hdms = ol.coordinate.toStringHDMS(ol.proj.transform( coordinate, 'EPSG:3857', 'EPSG:4326')); content.innerHTML = '

You clicked here:

' + hdms + ''; // 设置overlay的位置,从而显示在鼠标点击处 overlay.setPosition(coordinate); }); 注册/注销事件 // 监听singleclick事件 map.on('singleclick', function(event){ // 通过getEventCoordinate方法获取地理位置,再转换为wgs84坐标,并弹出对话框显示 alert(ol.proj.transform(map.getEventCoordinate(event), 'EPSG:3857', 'EPSG:4326')); }) var key = map.on('singleclick', function(event){ alert('这是一个演示如何取消事件监听的应用,之后再点击地图时,你将不会再看到这个说明。'); // 下面这行代码就是取消事件监听 map.unByKey(key); }) // 创建事件监听器 var singleclickListener = function(event){ alert('这是一个演示如何取消事件监听的应用,之后再点击地图时,你将不会再看到这个说明。'); // 在响应一次后,注销掉该监听器 map.un('singleclick', singleclickListener); }; map.on('singleclick', singleclickListener); // 使用once函数,只会响应一次事件,之后自动注销事件监听 map.once('singleclick', function(event){ alert('这是一个演示如何取消事件监听的应用,之后再点击地图时,你将不会再看到这个说明。'); }) 常用事件 常用鼠标事件 地图鼠标左键单击事件 对应的类为ol.Map,事件名为singleclick。 地图鼠标左键双击事件 对应的类为ol.Map,事件名为dblclick。 地图鼠标点击事件 对应的类为ol.Map,事件名为click。 地图鼠标移动事件 对应的类为ol.Map,事件名为pointermove。 地图鼠标拖拽事件 对应的类为ol.Map,事件名为pointerdrag。 地图移动事件 对应的类为ol.Map,事件名为moveend。

注意:在singleclick和dblclick响应之前,都会触发click事件,在选择事件时,需要谨慎考虑。 同时发现moveend事件在地图缩放的时候,也会触发。

非直接交互事件 地图缩放事件 对应的类为ol.View,事件名为 change:resolution 地图中心改变事件 对应的类是ol.View,事件名为 change:center 自定义事件

注意事件名称是可以自定义的,只要派发和监听使用的事件名称是一致的就可以。除了可以通过dispatchEvent({type: 'mousemove', event: event})这种形式派发一个事件之外,还可以通过dispatchEvent('mousemove')这中形式直接发送mousemove事件

// 为地图注册鼠标移动事件的监听 map.on('pointermove', function(event){ //forEachFeatureAtPixel--对矢量数据源,通过鼠标点击坐标与map坐标对比,获取选中要素 map.forEachFeatureAtPixel(event.pixel, function(feature){ // 为移动到的feature发送自定义的mousemove消息 feature.dispatchEvent({type: 'mousemove', event: event}); }); }); // 为feature1注册自定义事件mousemove的监听 feature1.on('mousemove', function(event){ // 修改feature的样式为半径100像素的园,用蓝色填充 this.setStyle(new ol.style.Style({ image: new ol.style.Circle({ radius: 100, fill: new ol.style.Fill({ color: 'blue' }) }) })); }); 交互-选中样式

feature的样式优先级是大于layer的样式的优先级

var layer2 = new ol.layer.Vector({ source: new ol.source.Vector(), // 注意:把feature上的style,直接移到layer上,避免直接在feature上设置style style: new ol.style.Style({ image: new ol.style.Circle({ radius: 10, fill: new ol.style.Fill({ color: 'red' }) }) }) }); var map2 = new ol.Map({ layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), layer2 ], target: 'map2', view: new ol.View({ center: ol.proj.transform( [104, 30], 'EPSG:4326', 'EPSG:3857'), zoom: 10 }) }); // 在地图上添加一个圆 var circle2 = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.transform( [104, 30], 'EPSG:4326', 'EPSG:3857')) }) // 此处不再为feature设置style layer2.getSource().addFeature(circle2); // 添加一个用于选择Feature的交互方式 map2.addInteraction(new ol.interaction.Select({ // 设置选中后的style style: new ol.style.Style({ image: new ol.style.Circle({ radius: 10, fill: new ol.style.Fill({ color: 'blue' }) }) }) })); //移入选中变色 // 添加一个用于选择Feature的交互方式 map.addInteraction(new ol.interaction.Select({ condition: ol.events.condition.pointerMove, // 唯一的不同之处,设置鼠标移到feature上就选取 style: new ol.style.Style({ image: new ol.style.Circle({ radius: 10, fill: new ol.style.Fill({ color: 'blue' }) }) }), //过滤条件 // 关键: 设置过了条件,可以用feature来写过滤,也可以用layer来写过滤 filter: function(feature, layer){ return layer === circleLayer; } })); //取消 // 添加一个用于选择Feature的交互方式 var clickSelect = new ol.interaction.Select({ style: new ol.style.Style({ image: new ol.style.Circle({ radius: 10, fill: new ol.style.Fill({ color: 'blue' }) }) }) }); map.addInteraction(clickSelect); // 取消选中 function unselectFeature() { clickSelect.getFeatures().clear(); // 下面这样也是可以取消选中的,根据情况选择 // map.removeInteraction(clickSelect); } 绘图 //画线为例 // 添加一个绘制的线使用的layer var lineLayer = new ol.layer.Vector({ source: new ol.source.Vector(), style: new ol.style.Style({ stroke: new ol.style.Stroke({ color: 'red', size: 1 }) }) }) map2.addLayer(lineLayer); map2.addInteraction(new ol.interaction.Draw({ type: 'LineString', source: lineLayer.getSource() // 注意设置source,这样绘制好的线,就会添加到这个source里 })); map.addInteraction(new ol.interaction.Draw({ type: 'LineString', // 设置绘制线 source: lineLayer.getSource() // 注意设置source,这样绘制好的线,就会添加到这个source里 }));


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有