openlayers学习

在一家互联网企业工作,工作接近一年,总结一下对openlayers的学习,主要是在vue项目中对openlayers的使用,希望可以对大家有所帮助~~

openlayers的安装说起把~

npm install ol

openlayers在项目中的引入

引入是按需引入,根据你所需要的来引入就好了

import 'ol/ol.css'
import Map from 'ol/Map'
import View from 'ol/View'
import { WMTS, Vector as VectorSource } from 'ol/source'
import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer'
import { Circle as CircleStyle, Fill, Stroke, Icon, Text, Style } from 'ol/style';
import WMTSTileGrid from 'ol/tilegrid/WMTS'
import Feature from 'ol/Feature'
import { XYZ,ImageWMS,TileWMS, Vector as VectorSource,WMTS } from "ol/source";
import { Tile as TileLayer, Image as ImageLayer,Vector as VectorLayer } from "ol/layer";

创建天地图

为了方便后面对地图的操作,可以将map定义成全局变量

data(){
  return{
    map:null,
    newcontent: null,
    newoverlay: null,
  }
},
mounted(){
  this.initMap()
},
methods:{
  initMap(){
    const map = new Map({
        target: 'map',
        // logo: false,
        layers: [],
        view: new View({
          // 地图视图
          projection: 'EPSG:4326', // 坐标系,有EPSG:4326和EPSG:3857
          center: [117.2531, 31.861184], // 坐标 安徽
          // minZoom: 10, // 地图缩放最小级别
          zoom: 8 // 地图缩放级别
        })
    })
    this.map = map
    const wkid = "EPSG:4326"
    //天地图底图
    this.addTiandiLayer("http://t{0-7}.tianditu.com/DataServer?T=vec_w&tk=申请的天地图 
    key&x= {x}&y={y}&l={z}",wkid)
    //天地图标注图层
    this.addTiandiLayer("'http://t{0-7}.tianditu.com/DataServer?T=cva_w&tk=申请的天地图 
    key&x= {x}&y={y}&l={z}'",wkid)
  },
   addTiandiLayer(url,wkid) {
     const source = new XYZ({
       url: url,
       projection: wkid
     });
     const tdtLayer = new TileLayer({
       source: source,
       visible: true
     });
  }
}

加载wms图层

addWMSLayer (url, layerId, id) {
      debugger
      const wmsLayer = new TileLayer({
        source: new TileWMS({
          url: url,
          params: {
            LAYERS: layerId,
            TILED: true,
            serverType: "geoserver",
          },
        }),
      });
      wmsLayer.set('id', id)
      this.map.addLayer(wmsLayer);
    }

加载wmts图层

function addWMTSLayer(url,type){
        var layer = null
        fetch(url, { mode: 'cors' }).then(function (response) {
          return response.text()
        }).then((text) => {
          const parser = new ol.format.WMTSCapabilities()
          const result = parser.read(text)
          const options = ol.source.WMTS.optionsFromCapabilities(result, {
            layer: result['Contents']['Layer'][0].Identifier,
            matrixSet: result['Contents']['TileMatrixSet'][0].Identifier,
            projection: projection
          })
          /**兼容不同引擎切图原点YX, XY */
          // const origins = options.tileGrid.origins_
          // let neworigins = origins.map(origin => {
          //   if (origin[0] > origin[1]) {
          //     return [origin[1], origin[0]]
          //   } else {
          //     return [origin[0], origin[1]]
          //   }
          // })
          // options.tileGrid.origins_ = neworigins
          layer = new ol.layer.Tile({
            source: new ol.source.WMTS((options)),
            visible: true
          })
          layer.set('id', '1111')
          map.addLayer(layer)
        })
      }

加载ArcgisRestTileLayer

addArcgisRestTileLayer (url, id) {
      const result = await this.$http.get(url + "?f=json")
      const data = result.data;
      let source = null;
      if (data.tileInfo) {
        const urlTemplate = url + '/tile/{z}/{y}/{x}';
        const tileInfo = data.tileInfo;
        const lods = tileInfo.lods.length
        let resolutions = new Array(lods);
        let matrixIds = new Array(lods);
        for (var z = 0; z < lods; ++z) {
          resolutions[z] = tileInfo.lods[z].resolution;
          matrixIds[z] = z;
        }
        const tileGrid = new TileGrid({
          origin: [tileInfo.origin.x, tileInfo.origin.y], //原点(左上角)
          resolutions: resolutions, //分辨率数组
          matrixIds: matrixIds //矩阵标识列表,与地图级数保持一致
        });
        source = new XYZ({
          maxZoom: lods,
          tileSize: tileInfo.cols,
          projection: this.projCode,
          tileGrid: tileGrid,
          tilePixelRatio: 2,
          tileUrlFunction: function (tileCoord) {
            let z = tileCoord[0];
            if (tileInfo.cols === 512) {
              z = tileCoord[0] + 1
            }
            return urlTemplate.replace('{z}', z.toString())
              .replace('{x}', tileCoord[1].toString())
              .replace('{y}', (-tileCoord[2] - 1).toString());
          },
        })
      } else {
        source = new TileArcGISRest({
          url: url + '/export'
        });
      }
      const arcgisLayer = new TileLayer({
        source: source
      })
      arcgisLayer.set('id', id)
      this.map.addLayer(arcgisLayer);
    }

加载矢量数据

以点为例,point.setProperties(data[i]);很重要,不写的话点击的时候获取不到point的属性数据

addPointData(){
  var source = new VectorSource();
  var layer = new VectorLayer({
      source: source
  });
  this.map.addLayer(layer);
  for (let i = 0; i < data.length; i++) {
    const point = new Feature({
      geometry: new Point([data[i].longitude, data[i].latitude])
    });
    point.setStyle(new Style({
      image: new Icon({
        src: require('../../../assets/icons/点.png')
      })
    }))
    point.setProperties(data[i]);//这点很重要,不写的话点击的时候获取不到point的属性数据
    source.addFeature(point);
    //layer.getSource().addFeature(point);
  }
}

添加点线面

function addGeometry(type,coordinate){
        var geometry = null
        if(type == 'point'){
          geometry = new ol.Feature({
            geometry: new ol.geom.Point(coordinate)
          });
          geometry.setProperties({
            name: '点',
            num: 11
          })
        }
        if(type == 'linestring'){
          geometry = new Feature({
            geometry: new LineString(coordinate)
          })
          geometry.setProperties({
            name: '线',
            num: 12
          })
        }
        if(type == 'polygon'){
          geometry = new Feature({
            geometry: new Polygon(coordinate)
          })
          geometry.setProperties({
            name: '面',
            num: 13
          })
        }
        geometry.setStyle((new Style({ //内部面选中样式
          fill: new Fill({
            color: 'rgba(32, 72, 145, 0.5)'
          }),
          stroke: new Stroke({
            color: '#00c4ff',
            width: 4
          }),
          image: new Circle({
            radius: 7,
            fill: new Fill({
              color: 'red'
            })
          })
        })))
        pointSource.addFeature(geometry);
      }

地图的几种事件

用到最多的应该就是单击事件了,目前见到的大概就是这么多了

map.on('click', this.mapClick);//地图点击
map.on('pointermove', this.mapPointerMove);//鼠标移入
map.on('singleclick', this.mapSingleClick);//地图单击
map.on('postcompose', this.animateFlights);//拖拽地图开始事件(不常用)
map.on('moveend', this.mapMoveEnd);//拖拽地图结束事件(不常用)

  地图事件详解——click单击事件的mapClick方法

当你点击地图的时候,就会触发这个方法

mapClick(evt){
  console.log(evt)//打印结果如下图
    if (this.map.hasFeatureAtPixel(evt.pixel)) {//判断是否点击的是加载的feature数据,点线面等
      //获取点击到的features,可能不止一个,根据需要取舍,在此取features[0]
      const features = this.map.getFeaturesAtPixel(evt.pixel);
      //可以对点击的feature进行一些操作,如显示点击图层的某个属性,以弹窗展示等等,或是设置点击feature高亮显示,当然这要根据具体功能来写了
    }
}

 这是打印出来的evt的结果,我们常用到的也就是上面的二个属性evt.pixelevt.coordinate

  这是打印出来的features的结果,我们常用到的也就是上面的二个属性features[0].values_

地图事件详解——pointermove移入事件的mapPointerMove方法

移入事件和点击事件是一样的,只不过触发方式不同

mapPointerMove(evt){
  console.log(evt)//打印结果如下图
    if (this.map.hasFeatureAtPixel(evt.pixel)) {//判断是否点击的是加载的feature数据,点线面等
      //获取点击到的features,可能不止一个,根据需要取舍,在此取features[0]
      const features = this.map.getFeaturesAtPixel(evt.pixel);
      //可以对点击的feature进行一些操作,如显示点击图层的某个属性,以弹窗展示等等,或是设置点击feature高亮显示,当然这要根据具体功能来写了
    }
}

地图弹窗实现

initMap修改

initMap(){
    var container = document.getElementById('popup');
    var content = document.getElementById('popupcontent');
    var overlay = new Overlay({
      element: container,
      autoPan: true,
      autoPanAnimation: {
           duration: 250
      }
    });
    const map = new Map({
        target: 'map',
        // logo: false,
        layers: [],
        view: new View({
          // 地图视图
          projection: 'EPSG:4326', // 坐标系,有EPSG:4326和EPSG:3857
          center: [117.2531, 31.861184], // 坐标 安徽
          // minZoom: 10, // 地图缩放最小级别
          zoom: 8 // 地图缩放级别
        }),
        overlays: [overlay]
    })
    this.map = map
    this.newoverlay = overlay
    this.newcontent = content
    const wkid = "EPSG:4326"
    //天地图底图
    this.addTiandiLayer("http://t{0-7}.tianditu.com/DataServer?T=vec_w&tk=申请的天地图 
    key&x= {x}&y={y}&l={z}",wkid)
    //天地图标注图层
    this.addTiandiLayer("'http://t{0-7}.tianditu.com/DataServer?T=cva_w&tk=申请的天地图 
    key&x= {x}&y={y}&l={z}'",wkid)
  },
mapClick(evt){
    if (this.map.hasFeatureAtPixel(evt.pixel)) {
      const features = this.map.getFeaturesAtPixel(evt.pixel);
      //判断点击的是否为点数据,面改为Polygon,线改为Line
      if(features[0].getGeometry() instanceof Point){
        const cor = evt.coordinate
        const data = features[0].values_
        this.addPopup(data,cor)//展示弹窗
      }else{
        this.newoverlay.setPosition(undefined);// 否则不显示
      }
    }
}
  addPopup(data,cor){
      if(data.name){
        this.newcontent.innerHTML = '<div><span>名称:</span><span 
        class="popup_code">' +
        data.name + '</span></div';
        this.newoverlay.setPosition(cor);
      }
      
    },

temlate

<div id="mapDiv" class="device-mapDiv"></div>
// 弹窗
 <div id="popup" class="ol-popup" style="background:rgba(32, 72, 145, 1);">
    <div id="popupcontent" class="popupcontent"></div>
 </div>

弹窗样式css

.ol-popup{
    position: relative;
    left: -100px;
    top: -55px;
    border-radius: 5px;
  }
  .popupcontent{
    height: 46px;
    padding: 10px;
    font-family: 'Open Sans';
    color: #FFF;
    font-size: 19px;
  }
  .ol-popup:after, .ol-popup:before {
    top: 100%;
    border: solid transparent;
    content: " ";
    height: 0;
    width: 0;
    position: absolute;
    pointer-events: none;
  }
  .ol-popup:after {
    // border-top-color: white;
    // border-width: 10px;
    left: 48px;
    margin-left: -10px;
  }
  .ol-popup:before {
    // border-top-color: #cccccc;
    // border-width: 11px;
    left: 48px;
    margin-left: -11px;
  }

点击事件就完成了,内容可以根据需要修改 

 如何加载矢量面的时候,将面的名称也显示出来

设置样式的时候加个text就好了

for (let i = 0; i < data.length; i++) {
  var source = new VectorSource();
  var layer = new VectorLayer({
      source: this.source
  });
  if (data[i].floor == selectfloor) {
    //wkt转feature数据
    let wkt = data[i].shape;
    let format = new WKT();
    let feature = format.readFeature(wkt);
    feature.setProperties(data[i]);
    source.addFeature(feature);
    feature.setStyle(addStyle(feature));
    function addStyle () {
      let style = new Style({
        fill: new Fill({
          color: '#0e2036'
        }),
        stroke: new Stroke({
          color: '#5b91bb',
          width: 3
         }),
         text: new Text({
           text: `${feature.getProperties().name}`,
           textAlign: 'center',
           font: 'bold 12px sans-serif',
           fill: new Fill({
             color: '#7bb5e1'
           })
         })
       });
       return style;
     }
   }
}

图层层级顺序修改

layer.setZIndex(index)

图层透明度修改

layer.setOpacity(alpha)

删除layer

removeLayer (id) {
      const layers = this.map.getLayers();
      let layer = null;
      layers.forEach(item => {
        if (item.get('id') === id) {
          layer = item;
          return;
        }
      })
      if (layer) {
        this.map.removeLayer(layer);
      }
    }

加载wkt数据

 this.source = new VectorSource()
 this.layer = new VectorLayer({
      source: this.source,
      style: new Style({
        fill: new Fill({
         color: 'red'
        }),
        stroke: new Stroke({
         color: 'red',
         width: 2
       }),
       image: new CircleStyle({
        radius: 7,
        fill: new Fill({
         color: 'red'
       })
     })
   })
 });
 this.map.addLayer(this.layer)

 let wkt = data// data为wkt数据
 let feature = format.readFeature(wkt);
 feature.setProperties(xxx)// 为feature数据设置属性
 this.source.addFeature(feature);

编辑shape

addDraw(type) {
            // 编辑shape数据
            this.modify = new Modify({
                source: this.source
            });
            this.map.addInteraction(this.modify);
            // const that = this;
            this.modify.on('modifyend', (evt) => {
                let feature = evt.features.item(0)
            });
            // 绘制shape数据   
            const draw = new Draw({
                source: this.source,
                type: type
            });
            this.map.addInteraction(draw);
            let snap = new Snap({ source: this.source });
            this.map.addInteraction(snap);
            draw.setActive(true);

            //绘制结束
            draw.on('drawend', (e) => {
                draw.setActive(false);
                //绘制出的要素
                let feature = e.feature
            });
  }

定位到选中数据并高亮

selectFeature(data) {// data所选择数据
        this.source.forEachFeature(feature => {
                // console.log(feature.getProperties())
                if ((data === feature.getProperties().id)) {
                    const MapZoom = feature.getGeometry().getExtent();
                    // let mapPadding = [20, 10, 20, 10];
                    this.map.getView().fit(MapZoom, this.map.getSize(), {
                        constrainResolution: false,
                        earest: false
                        // padding: mapPadding
                    });
                    feature.setStyle(selectStyle());
                }
            });

            function selectStyle() {
                let style = new Style({
                    fill: new Fill({
                        color: 'rgba(255, 255, 255, 0.2)'
                    }),
                    stroke: new Stroke({
                        color: '#ffcc33',
                        width: 2
                    }),
                    image: new CircleStyle({
                        radius: 7,
                        fill: new Fill({
                            color: '#ffcc33'
                        })
                    })
                });
                return style;
            }
        }

移除图层

removeLayer (id) {
      const layers = this.map.getLayers();
      let layer = null;
      layers.forEach(item => {
        if (item.get('id') === id) {
          layer = item;
        }
      })
      if (layer) {
        this.map.removeLayer(layer);
      }
 }

先更新到这了,之后遇到问题会持续更新~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我就是你的语法糖️

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值