openlayers基础知识和常规操作

3,292 阅读16分钟

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

快速开始

  • 引入openlayers相关资源
  • 创建一个
    作为地图容器
  • 使用JavaScript创建一个简单的地图
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/css/ol.css" type="text/css">
    <style>
      .map {
        height: 400px;
        width: 100%;
      }
    </style>
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/build/ol.js"></script>
    <title>OpenLayers example</title>
  </head>
  <body>
    <h2>My Map</h2>
    <div id="map" class="map"></div>
    <script type="text/javascript">
      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
        })
      });
    </script>
  </body>
</html>

常用类简介

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;

事件触发

行为

各种类型的图层

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.** 修改控件的可选参数的默认值**

<div  id="mouse-position" class="mouse-position-wrapper">
    <div class="custom-mouse-position"></div>
</div>
  .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加载图标

<div id="map" style="width: 100%"></div>
<!--下面就是传统的显示一个图片图标的方式,用img-->
<div id="anchor"><img src="../img/anchor.png" alt="示例锚点"/></div>

 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 = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="30px" height="30px" viewBox="0 0 30 30" enable-background="new 0 0 30 30" xml:space="preserve">'+    
'<path fill="#156BB1" d="M22.906,10.438c0,4.367-6.281,14.312-7.906,17.031c-1.719-2.75-7.906-12.665-7.906-17.031S10.634,2.531,15,2.531S22.906,6.071,22.906,10.438z"/>'+
'<circle fill="#FFFFFF" cx="15" cy="10.677" r="3.291"/></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的数量,从而提高效率

提示信息

<!--此处用html布局,各种样式均在css中定义好了-->
<div id="popup" class="ol-popup">
  <a href="#" id="popup-closer" class="ol-popup-closer"></a>
  <div id="popup-content"></div>
</div>

......

<script>
  // 获取到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 = '<p>You clicked here:</p><code>' + hdms +
        '</code>';
    // 设置overlay的位置,从而显示在鼠标点击处
    overlay.setPosition(coordinate);
  });

</script>
  

注册/注销事件

// 监听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的样式的优先级

<div id="map2" style="width: 100%"></div>
<script type="text/javascript">
    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);
    }
</script>

绘图

//画线为例
// 添加一个绘制的线使用的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里
	}));