前端开发之:openlayers框架,地图相关开发中常见功能

功能实现

工作中一般需要解决的一些常见功能

画线并编辑 api:draw, modify

添加绘制功能 draw

注意事项: 在添加绘制功能之前,应提前先在地图渲染时,为绘制功能添加一个矢量图层

  import VectorLayer from 'ol/layer/Vector'
  import VectorSource from ol/source/Vector
  let drawsource = new VectorSource()
  let drawvector = new VectorLayer({
  source: drawsource,
  });
  map.addLayer(drawvector)

添加绘制功能

  import {Draw, Snap} from 'ol/interaction'
  let draw = new Draw({
  source: drawsource, //之前预先创建的图层的 `drawsource`
  }
  map.addInteraction(draw)
  let snap = new Snap({source: drawsource}) //snap 捕捉并处理绘制以及修改时的矢量元素
  map.addInteraction(snap)
绘制中设置动态样式
  • 绘制中动态样式,是在用户绘制过程中显示的样式,并非绘制结束最终的样式
  • openlayers 中 Draw 对象有一个 Style 属性, Style 可以是一个样式数组,也可以是一个函数(返回一个样式数组; 这个函数有两个参数 分别是: fearture(绘制中的), resolution(视图的分辨率))
  • 这里我们的思路就是: 通过style 函数的fearture 参数来获取绘制点,并为之添加样式

    是在添加绘制功能的时候添加样式
    
    import {Draw, Snap} from 'ol/interaction'
    let draw = new Draw({
    source: drawsource, //之前预先创建的图层的 `drawsource`
    style(feature, r){
    // **重点: 此处的 feature 是跟随鼠标的变化实时的数据,不是你绘制的点的数据 **
    // ** 指定绘制点添加样式** :用到 Style 的一个可以指定 geometry 来添加样式
    let coords = feature.getGeometry().getCoordinates()
    let styles = []
    for(let i in coords){
      styles.push(new Style({
        geometry: new Point(coords[i]) //指定点
        ... //此处写你的样式 
      }))
    }
    return styles
    }
    }
    map.addInteraction(draw)
    绘制结束事件监听

    openlayers 中的 draw 绘制结束事件监听api: drawend, 回调函数有一个DrawEvent(feature: Feature {…}, target: Draw{…}, type: drawend) 的参数, 此处的是你最终绘制的DrawEvent.feature

    draw.on('drawend', (drawEvent)=>{
    let feature = drawEvent.feature
    ... //进行各种操作
    })  
添加修改功能 modify
  • 注意事项:修改功能是添加在矢量图层上的,所以需在添加图层的时候加载
    
    let modify = new Modify({
    source: drawsource
    })
    map.addInteraction(modify)

##### 修改中的动态样式

- openlayers modify 有一个 modifyend 的事件,回调函数参数:ModifyEvent(features: Collection {…}, mapBrowserEvent: MapBrowserEvent {…}, target: Modify {…}, type: modifyend), 我们此处使用 ModifyEvent.features
```javascript
  modify.on('modifyend', (e)=>{
  let feature = e.features.array_[0]
  ... //进行各种操作
  })

坐标转换

  • openlayers 默认坐标系是同谷歌地图一样的 EPSG:3857, 国内常用的坐标系是84坐标系EPSG:4326,此时坐标系转换功能就是必需的了
coordinate坐标
source坐标的坐标系
destination目标坐标系
  import { transform } from 'ol/proj'
  let oldCoord = [13031076.441730658, 4735129.733960388] //EPSG:3857
  let oldCoord84 = [117.16932799710696, 39.088029694977024] //EPSG:4326
  let coordinate84 = new transform(oldCoord, EPSG:3857, EPSG:4326); //转换为84坐标系
  let coordinate = new transform(oldCoord84, EPSG:3857, EPSG:4326); //转换为Google Web 墨卡托坐标系

坐标比较

  • 在做绘制和修改功能时,不免需要进行前后坐标的对比,而坐标是一个数组模式的数据,这就涉及到数组的对比方式了。
    let oldCoordinate = [13031076.441730658, 4735129.733960388]
    let newCoordinate = [13031152.878758943, 4733983.178536111]
    oldCoordinate.toString() === newCoordinate.toString() //此处使用转换为字符串进行比较,数组的顺序与值同时相同才能代表坐标的相同

地图实现蒙层

  • 给地图添加一层polygon,并置于底层

单击地图事件监听

openlayers 中的 map对象有一个 singleclick事件,回调函数参数:

MapBrowserEvent {type: singleclick, target: Map, map: Map, frameState: {…}, originalEvent: PointerEvent, pixel_: Array(2), target: Map, type: singleclick, coordinate: Array(2), pixel: Array(2)}
map.on('singleclick', (e)=>{
    //需要获取到矢量图层可以使用: map.forEachLayerAtPixel(pixel, callback, opt_options), 获取坐标:       map.getCoordinateFromPixel(pixel)
        map.forEachFeatureAtPixel(e.pixel, (feature)=>{
         //...数据处理 此处为你点击的 feature 
          }, {
            //options: layerFilter | hitTolerance | checkWrapped})
 })

地图可视范围监听

此处是在地图的可视范围发生变化时,通过监听地图的moveend事件进而获取当前的可视范围

  import {getTopLeft, getTopRight, getBottomLeft, getBottomRight} from 'ol/extent'
  map.on('moveend', (event)=>{
  //获取可视化区域得范围
  let coods = event.map.getView().calculateExtent( event.map.getSize()),
  postcooders = [getTopLeft(coods), getTopRight(coods), getBottomRight(coods) ,getBottomLeft(coods), getTopLeft(coods)]; //可视区域为一个多边形,需是闭合的
  })

串线多样式编辑

openlayers Style 对象可以接收一个数组,对于同一条串线可以有多种不同的样式,只需按照你的样式顺序添加即可

  import Feature from 'ol/Feature';
  import LineString from 'ol/geom/LineString';
  import Style from 'ol/style/Style';
  let lineFeature = new Feature(new LineString([coordinates]))
  let yourStyle1 = new Style({...}), yourStyle2 = new Style({...});
  let yourStyles = [yourStyle1, yourStyle2, ...] //依次添加要用 Array.prototype.push(), 解构语言是不支持的
  lineFeature.setStyle(yourStyles)

带箭头的串线样式编辑

大概思路: 获取串线的最后两个点=>计算出串线的走向=>为最终点添加箭头图标(含串线走向的属性)

  import {Point} from 'ol/geom'
  //start 串线走向计算第一个点, end 串线最终点, iconImg 串线最终的箭头图标
  arrowIcon(start, end, iconImg){
    let feature = new Feature({
      geometry: new Point(end),
    });
    let rotation = Math.atan2(end[0] - start[0], end[1] - start[1]); //计算串线走向
    feature.setStyle(
      new Style({
        image: new Icon({
          anchor: [0.5, 0.5],
          src: iconImg,
          rotateWithView: true, // 图标旋转到串线走向
          rotation: rotation, //图标旋转到串线走向
          ...
        }),
      })
    );
    return feature
  },

绘制多边形 (闭合的形状)

多边形是一个闭合的形状,所以坐标组第一和最后一个坐标一样

  import { Polygon } from 'ol/geom'
  // coords = [[long, lat],[long, lat],[long, lat], ...]
  let yourPolygon = new Polygon([coords])
  //...更多api请查看官网

覆盖物的实时位置监听

openlayers overlay 有一个 setPosition的方法, 只需接收到数据,使用此方法即可修改覆盖物的位置

  <div id=overlayEl ><img src=...></div>

  import { Overlay } from ol
  let yourOverlay =  new Overlay(
  {
    id: realair,
    element: document.getElementById(realAir),
    position: this.coordTransform(realFeatures),
    positioning: center-center,
    offset: [3, 10]
  })
  map.addOverlay(yourOverlay);
  yourOverlay.setPosition(newCoordinate) //newCoordinate 覆盖物的新坐标
上一篇
下一篇