当前位置:   article > 正文

openlayers学习_引入openlayer

引入openlayer

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

openlayers的安装说起把~

npm install ol

openlayers在项目中的引入

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

  1. import 'ol/ol.css'
  2. import Map from 'ol/Map'
  3. import View from 'ol/View'
  4. import { WMTS, Vector as VectorSource } from 'ol/source'
  5. import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer'
  6. import { Circle as CircleStyle, Fill, Stroke, Icon, Text, Style } from 'ol/style';
  7. import WMTSTileGrid from 'ol/tilegrid/WMTS'
  8. import Feature from 'ol/Feature'
  9. import { XYZ,ImageWMS,TileWMS, Vector as VectorSource,WMTS } from "ol/source";
  10. import { Tile as TileLayer, Image as ImageLayer,Vector as VectorLayer } from "ol/layer";

创建天地图

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

  1. data(){
  2. return{
  3. map:null,
  4. newcontent: null,
  5. newoverlay: null,
  6. }
  7. },
  8. mounted(){
  9. this.initMap()
  10. },
  11. methods:{
  12. initMap(){
  13. const map = new Map({
  14. target: 'map',
  15. // logo: false,
  16. layers: [],
  17. view: new View({
  18. // 地图视图
  19. projection: 'EPSG:4326', // 坐标系,有EPSG:4326和EPSG:3857
  20. center: [117.2531, 31.861184], // 坐标 安徽
  21. // minZoom: 10, // 地图缩放最小级别
  22. zoom: 8 // 地图缩放级别
  23. })
  24. })
  25. this.map = map
  26. const wkid = "EPSG:4326"
  27. //天地图底图
  28. this.addTiandiLayer("http://t{0-7}.tianditu.com/DataServer?T=vec_w&tk=申请的天地图
  29. key&x= {x}&y={y}&l={z}",wkid)
  30. //天地图标注图层
  31. this.addTiandiLayer("'http://t{0-7}.tianditu.com/DataServer?T=cva_w&tk=申请的天地图
  32. key&x= {x}&y={y}&l={z}'",wkid)
  33. },
  34. addTiandiLayer(url,wkid) {
  35. const source = new XYZ({
  36. url: url,
  37. projection: wkid
  38. });
  39. const tdtLayer = new TileLayer({
  40. source: source,
  41. visible: true
  42. });
  43. }
  44. }

加载wms图层

  1. addWMSLayer (url, layerId, id) {
  2. debugger
  3. const wmsLayer = new TileLayer({
  4. source: new TileWMS({
  5. url: url,
  6. params: {
  7. LAYERS: layerId,
  8. TILED: true,
  9. serverType: "geoserver",
  10. },
  11. }),
  12. });
  13. wmsLayer.set('id', id)
  14. this.map.addLayer(wmsLayer);
  15. }

加载wmts图层

  1. function addWMTSLayer(url,type){
  2. var layer = null
  3. fetch(url, { mode: 'cors' }).then(function (response) {
  4. return response.text()
  5. }).then((text) => {
  6. const parser = new ol.format.WMTSCapabilities()
  7. const result = parser.read(text)
  8. const options = ol.source.WMTS.optionsFromCapabilities(result, {
  9. layer: result['Contents']['Layer'][0].Identifier,
  10. matrixSet: result['Contents']['TileMatrixSet'][0].Identifier,
  11. projection: projection
  12. })
  13. /**兼容不同引擎切图原点YX, XY */
  14. // const origins = options.tileGrid.origins_
  15. // let neworigins = origins.map(origin => {
  16. // if (origin[0] > origin[1]) {
  17. // return [origin[1], origin[0]]
  18. // } else {
  19. // return [origin[0], origin[1]]
  20. // }
  21. // })
  22. // options.tileGrid.origins_ = neworigins
  23. layer = new ol.layer.Tile({
  24. source: new ol.source.WMTS((options)),
  25. visible: true
  26. })
  27. layer.set('id', '1111')
  28. map.addLayer(layer)
  29. })
  30. }

加载ArcgisRestTileLayer

  1. addArcgisRestTileLayer (url, id) {
  2. const result = await this.$http.get(url + "?f=json")
  3. const data = result.data;
  4. let source = null;
  5. if (data.tileInfo) {
  6. const urlTemplate = url + '/tile/{z}/{y}/{x}';
  7. const tileInfo = data.tileInfo;
  8. const lods = tileInfo.lods.length
  9. let resolutions = new Array(lods);
  10. let matrixIds = new Array(lods);
  11. for (var z = 0; z < lods; ++z) {
  12. resolutions[z] = tileInfo.lods[z].resolution;
  13. matrixIds[z] = z;
  14. }
  15. const tileGrid = new TileGrid({
  16. origin: [tileInfo.origin.x, tileInfo.origin.y], //原点(左上角)
  17. resolutions: resolutions, //分辨率数组
  18. matrixIds: matrixIds //矩阵标识列表,与地图级数保持一致
  19. });
  20. source = new XYZ({
  21. maxZoom: lods,
  22. tileSize: tileInfo.cols,
  23. projection: this.projCode,
  24. tileGrid: tileGrid,
  25. tilePixelRatio: 2,
  26. tileUrlFunction: function (tileCoord) {
  27. let z = tileCoord[0];
  28. if (tileInfo.cols === 512) {
  29. z = tileCoord[0] + 1
  30. }
  31. return urlTemplate.replace('{z}', z.toString())
  32. .replace('{x}', tileCoord[1].toString())
  33. .replace('{y}', (-tileCoord[2] - 1).toString());
  34. },
  35. })
  36. } else {
  37. source = new TileArcGISRest({
  38. url: url + '/export'
  39. });
  40. }
  41. const arcgisLayer = new TileLayer({
  42. source: source
  43. })
  44. arcgisLayer.set('id', id)
  45. this.map.addLayer(arcgisLayer);
  46. }

加载矢量数据

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

  1. addPointData(){
  2. var source = new VectorSource();
  3. var layer = new VectorLayer({
  4. source: source
  5. });
  6. this.map.addLayer(layer);
  7. for (let i = 0; i < data.length; i++) {
  8. const point = new Feature({
  9. geometry: new Point([data[i].longitude, data[i].latitude])
  10. });
  11. point.setStyle(new Style({
  12. image: new Icon({
  13. src: require('../../../assets/icons/点.png')
  14. })
  15. }))
  16. point.setProperties(data[i]);//这点很重要,不写的话点击的时候获取不到point的属性数据
  17. source.addFeature(point);
  18. //layer.getSource().addFeature(point);
  19. }
  20. }

添加点线面

  1. function addGeometry(type,coordinate){
  2. var geometry = null
  3. if(type == 'point'){
  4. geometry = new ol.Feature({
  5. geometry: new ol.geom.Point(coordinate)
  6. });
  7. geometry.setProperties({
  8. name: '点',
  9. num: 11
  10. })
  11. }
  12. if(type == 'linestring'){
  13. geometry = new Feature({
  14. geometry: new LineString(coordinate)
  15. })
  16. geometry.setProperties({
  17. name: '线',
  18. num: 12
  19. })
  20. }
  21. if(type == 'polygon'){
  22. geometry = new Feature({
  23. geometry: new Polygon(coordinate)
  24. })
  25. geometry.setProperties({
  26. name: '面',
  27. num: 13
  28. })
  29. }
  30. geometry.setStyle((new Style({ //内部面选中样式
  31. fill: new Fill({
  32. color: 'rgba(32, 72, 145, 0.5)'
  33. }),
  34. stroke: new Stroke({
  35. color: '#00c4ff',
  36. width: 4
  37. }),
  38. image: new Circle({
  39. radius: 7,
  40. fill: new Fill({
  41. color: 'red'
  42. })
  43. })
  44. })))
  45. pointSource.addFeature(geometry);
  46. }

地图的几种事件

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

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

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

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

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

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

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

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

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

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

地图弹窗实现

initMap修改

  1. initMap(){
  2. var container = document.getElementById('popup');
  3. var content = document.getElementById('popupcontent');
  4. var overlay = new Overlay({
  5. element: container,
  6. autoPan: true,
  7. autoPanAnimation: {
  8. duration: 250
  9. }
  10. });
  11. const map = new Map({
  12. target: 'map',
  13. // logo: false,
  14. layers: [],
  15. view: new View({
  16. // 地图视图
  17. projection: 'EPSG:4326', // 坐标系,有EPSG:4326和EPSG:3857
  18. center: [117.2531, 31.861184], // 坐标 安徽
  19. // minZoom: 10, // 地图缩放最小级别
  20. zoom: 8 // 地图缩放级别
  21. }),
  22. overlays: [overlay]
  23. })
  24. this.map = map
  25. this.newoverlay = overlay
  26. this.newcontent = content
  27. const wkid = "EPSG:4326"
  28. //天地图底图
  29. this.addTiandiLayer("http://t{0-7}.tianditu.com/DataServer?T=vec_w&tk=申请的天地图
  30. key&x= {x}&y={y}&l={z}",wkid)
  31. //天地图标注图层
  32. this.addTiandiLayer("'http://t{0-7}.tianditu.com/DataServer?T=cva_w&tk=申请的天地图
  33. key&x= {x}&y={y}&l={z}'",wkid)
  34. },
  35. mapClick(evt){
  36. if (this.map.hasFeatureAtPixel(evt.pixel)) {
  37. const features = this.map.getFeaturesAtPixel(evt.pixel);
  38. //判断点击的是否为点数据,面改为Polygon,线改为Line
  39. if(features[0].getGeometry() instanceof Point){
  40. const cor = evt.coordinate
  41. const data = features[0].values_
  42. this.addPopup(data,cor)//展示弹窗
  43. }else{
  44. this.newoverlay.setPosition(undefined);// 否则不显示
  45. }
  46. }
  47. }
  48. addPopup(data,cor){
  49. if(data.name){
  50. this.newcontent.innerHTML = '<div><span>名称:</span><span
  51. class="popup_code">' +
  52. data.name + '</span></div';
  53. this.newoverlay.setPosition(cor);
  54. }
  55. },

temlate

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

弹窗样式css

  1. .ol-popup{
  2. position: relative;
  3. left: -100px;
  4. top: -55px;
  5. border-radius: 5px;
  6. }
  7. .popupcontent{
  8. height: 46px;
  9. padding: 10px;
  10. font-family: 'Open Sans';
  11. color: #FFF;
  12. font-size: 19px;
  13. }
  14. .ol-popup:after, .ol-popup:before {
  15. top: 100%;
  16. border: solid transparent;
  17. content: " ";
  18. height: 0;
  19. width: 0;
  20. position: absolute;
  21. pointer-events: none;
  22. }
  23. .ol-popup:after {
  24. // border-top-color: white;
  25. // border-width: 10px;
  26. left: 48px;
  27. margin-left: -10px;
  28. }
  29. .ol-popup:before {
  30. // border-top-color: #cccccc;
  31. // border-width: 11px;
  32. left: 48px;
  33. margin-left: -11px;
  34. }

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

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

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

  1. for (let i = 0; i < data.length; i++) {
  2. var source = new VectorSource();
  3. var layer = new VectorLayer({
  4. source: this.source
  5. });
  6. if (data[i].floor == selectfloor) {
  7. //wkt转feature数据
  8. let wkt = data[i].shape;
  9. let format = new WKT();
  10. let feature = format.readFeature(wkt);
  11. feature.setProperties(data[i]);
  12. source.addFeature(feature);
  13. feature.setStyle(addStyle(feature));
  14. function addStyle () {
  15. let style = new Style({
  16. fill: new Fill({
  17. color: '#0e2036'
  18. }),
  19. stroke: new Stroke({
  20. color: '#5b91bb',
  21. width: 3
  22. }),
  23. text: new Text({
  24. text: `${feature.getProperties().name}`,
  25. textAlign: 'center',
  26. font: 'bold 12px sans-serif',
  27. fill: new Fill({
  28. color: '#7bb5e1'
  29. })
  30. })
  31. });
  32. return style;
  33. }
  34. }
  35. }

图层层级顺序修改

layer.setZIndex(index)

图层透明度修改

layer.setOpacity(alpha)

删除layer

  1. removeLayer (id) {
  2. const layers = this.map.getLayers();
  3. let layer = null;
  4. layers.forEach(item => {
  5. if (item.get('id') === id) {
  6. layer = item;
  7. return;
  8. }
  9. })
  10. if (layer) {
  11. this.map.removeLayer(layer);
  12. }
  13. }

加载wkt数据

  1. this.source = new VectorSource()
  2. this.layer = new VectorLayer({
  3. source: this.source,
  4. style: new Style({
  5. fill: new Fill({
  6. color: 'red'
  7. }),
  8. stroke: new Stroke({
  9. color: 'red',
  10. width: 2
  11. }),
  12. image: new CircleStyle({
  13. radius: 7,
  14. fill: new Fill({
  15. color: 'red'
  16. })
  17. })
  18. })
  19. });
  20. this.map.addLayer(this.layer)
  21. let wkt = data// data为wkt数据
  22. let feature = format.readFeature(wkt);
  23. feature.setProperties(xxx)// 为feature数据设置属性
  24. this.source.addFeature(feature);

编辑shape

  1. addDraw(type) {
  2. // 编辑shape数据
  3. this.modify = new Modify({
  4. source: this.source
  5. });
  6. this.map.addInteraction(this.modify);
  7. // const that = this;
  8. this.modify.on('modifyend', (evt) => {
  9. let feature = evt.features.item(0)
  10. });
  11. // 绘制shape数据
  12. const draw = new Draw({
  13. source: this.source,
  14. type: type
  15. });
  16. this.map.addInteraction(draw);
  17. let snap = new Snap({ source: this.source });
  18. this.map.addInteraction(snap);
  19. draw.setActive(true);
  20. //绘制结束
  21. draw.on('drawend', (e) => {
  22. draw.setActive(false);
  23. //绘制出的要素
  24. let feature = e.feature
  25. });
  26. }

定位到选中数据并高亮

  1. selectFeature(data) {// data所选择数据
  2. this.source.forEachFeature(feature => {
  3. // console.log(feature.getProperties())
  4. if ((data === feature.getProperties().id)) {
  5. const MapZoom = feature.getGeometry().getExtent();
  6. // let mapPadding = [20, 10, 20, 10];
  7. this.map.getView().fit(MapZoom, this.map.getSize(), {
  8. constrainResolution: false,
  9. earest: false
  10. // padding: mapPadding
  11. });
  12. feature.setStyle(selectStyle());
  13. }
  14. });
  15. function selectStyle() {
  16. let style = new Style({
  17. fill: new Fill({
  18. color: 'rgba(255, 255, 255, 0.2)'
  19. }),
  20. stroke: new Stroke({
  21. color: '#ffcc33',
  22. width: 2
  23. }),
  24. image: new CircleStyle({
  25. radius: 7,
  26. fill: new Fill({
  27. color: '#ffcc33'
  28. })
  29. })
  30. });
  31. return style;
  32. }
  33. }

移除图层

  1. removeLayer (id) {
  2. const layers = this.map.getLayers();
  3. let layer = null;
  4. layers.forEach(item => {
  5. if (item.get('id') === id) {
  6. layer = item;
  7. }
  8. })
  9. if (layer) {
  10. this.map.removeLayer(layer);
  11. }
  12. }

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/542112
推荐阅读