前端开发之: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
    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 覆盖物的新坐标
    
上一篇
下一篇