文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Vue结合openlayers按照经纬度坐标实现锚地标记及绘制多边形区域

2024-04-02 19:55

关注

前言

本文介绍vue结合openlayers实现根据返回的经纬度坐标完成锚地标记、绘制多边形区域;

注意点:

1.根据返回的经纬度取第一个坐标作为锚地图标位置;

2.根据返回的经纬度坐标数据,这里的后台数据需要处理(根据返回的数据处理成需要的格式),得到坐标数组渲染绘制区域画图显示在航道图层上。

3.关于数据渲染的问题:

这里前端采用的是获取左下角和右上角经纬度作为参数传递给后台获取当前屏幕显示的区域的数据。利用滑动地图区域来请求接口渲染数据,这样就很好的解决了一次性加载很多的数据的问题。

文章内容较长,花费时间需要一些时间,如果有疑问可留言、评论;以往也有发布关于openlayers的其它文章,可在本博客订阅搜索查看。

openlayers官方文档学习:

传送门

实现效果图预览:

实现步骤:

1.安装openlayers

cnpm i -S ol
#或者
npm install ol

2.引入模块

// openlayers地图
import "ol/ol.css";
import { Icon, Style ,Text,Fill,Stroke,Circle as CircleStyle} from "ol/style";
import Map from "ol/Map";
import View from "ol/View";
// import OSM from "ol/source/OSM";
import TileLayer from "ol/layer/Tile";
import XYZ from "ol/source/XYZ";
import { get as getProjection ,fromLonLat} from "ol/proj.js";
import { getBottomLeft, getTopRight } from "ol/extent.js";
import { Vector as SourceVec } from "ol/source";
import { Vector as LayerVec } from "ol/layer";
import Overlay from "ol/Overlay"; //弹窗
import { Point } from "ol/geom";
import { Feature } from "ol";
import Observable from 'ol/Observable';
import { defaults as defaultControls } from "ol/control"; //默认缩放
import { FullScreen, ScaleLine, ZoomSlider } from "ol/control"; //全屏,比例尺控件
import TileGrid from "ol/tilegrid/TileGrid";
import { LineString, Polygon } from "ol/geom.js";
import {defaults as defaultInteractions} from 'ol/interaction';//旋转

3.地图与弹窗html样式

<!-- 地图 -->
<div style="width:100%;height:100%">
    <div id="mapDiv"></div>
    <!-- 弹窗元素 -->
    <div class="popup serchPopup" ref="popup" v-show="shopPopup" >
                <div class="ship-header">
                  <div class="cname">{{anchorageName?anchorageName:""}}</div>
                      <img class="icon-close" @click="closePopup" src="../../assets/img/sy_close.png"/>
                </div>
    </div>
</div>

.popup {
  font-family: "微软雅黑";
  // min-width: 280px;
  position: relative;
  display: flex;
  flex-direction: column;
  transform: translate(-50%, calc(-100% - 12px));
  opacity: 0.95;
  background: #ffffff;
  border-radius: 24px;
  box-shadow: 0px 2px 20px 0px rgba(0, 0, 0, 0.15);
  // overflow: hidden;
  .content {
    margin-top: 6px;
  }
  .ship-header {
    padding: 20px 30px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    .cname {
      font-weight: 600;
      font-size: 32px;
      color: #024ee0;
    }
  }
  .ship-content {
    padding: 30px;
    border-top: 1px solid #ececec;
    font-size: 24px;
    font-weight: 500;
    color: #535f8b;
    .con-sx {
      display: flex;
      justify-content: space-between;
      .txt-margin {
        margin-right: 60px;
      }
    }
  }
}

.serchPopup::after {
    display: block;
    content: "";
    width: 0;
    height: 0;
    position: absolute;
    border: 12px solid transparent;
    border-top-color: #fff;
    bottom: -23px;
    left: 50%;
    transform: translateX(-50%);
} 

.icon-close {
  cursor: pointer;
  width: 24px;
  height: 24px;
}

4.data数据定义

根据需要的自己补充

data(){
     // 地图
     map:null,
     cjinobeaconMap:null,
    //默认加载中心点
    center: {
        longitude: "114.293726",//114.293726   113.306100
        latitude: "30.577845",//30.577845  29.629998
    },
    anchorageIcon:require("../../assets/img/anchorage_icon.png"),//锚地图标
    anchorageVector:false,
    anchorageVectorLayer:null,
    anchorageFeatures:[],
    drawSource: null,
}

5.methods方法

初始化

initMap() {
      let defaultsMap = {
        tileUrl1:"图层数据地址",
        origin: [-400, 400],
        zoom: 7,
        resolutions: [
          //根据需求添加区域
        ],
        fullExtent: [
          //根据需求添加区域
        ],
        inters: [1000, 100],
        center: [this.center.longitude, this.center.latitude],
        projection: getProjection("EPSG:4326")
      };
      // 航道图层
      this.cjinobeaconMap = new TileLayer({
        source: new XYZ({
          tileGrid: tileGrid,
          projection: defaultsMap.projection,
          url: defaultsMap.tileUrl1
        }),
        zIndex: 9
      });
      // 弹窗
      this.overlay = new Overlay({
        element: this.$refs.popup, // 弹窗标签,在html里
        autoPan: true, // 如果弹窗在底图边缘时,底图会移动
        autoPanAnimation: {
          // 底图移动动画
          duration: 250
        },
        stopEvent: false,
        offset: [0, -10],
        className:"popupOverlay",
      });
      // 加载地图
      this.map = new Map({
        target: "mapDiv",
        controls: defaultControls().extend([
          new FullScreen(),
          new ScaleLine({
            units: "metric"
          })
          // new ZoomSlider()
        ]),
        interactions: defaultInteractions({
          pinchRotate: false // 移动端禁止地图旋转
        }),
        loadTilesWhileAnimating: true,
        layers: [this.cjinobeaconMap],//保留航道图层
        overlays: [this.overlay], // 把弹窗加入地图
        view: new View({
          projection: defaultsMap.projection,
          center: defaultsMap.center,  center: [114.272172,30.564646],
          extent: defaultsMap.fullExtent,
          // resolutions: defaultsMap.resolutions,
          zoom: 14,
          // minZoom: 12,
          // maxZoom:17,
          //设置缩放级别为整数 
          // constrainResolution: true, 
          //关闭无级缩放地图
          smoothResolutionConstraint: false
        })
      });
      this.mapClick(); // 初始化地图成功后,给地图添加点击事件
      this.map.addEventListener("moveend", this.showView);//监听地图区域滑动
    },

动态显示图层

    showView() {
      let zoom = this.map.getView().getZoom();
      console.log(zoom,"缩放")
      this.map.getLayers().getArray().forEach((item) => {
          if (item.get("name") == "anchorageVectorLayer") {
                // 锚地,这里根据获取的层级显示隐藏数据
                if (zoom>13) {
                      item.setVisible(true);
                      this.getAnchorageData();
                    } else {
                      this.shopPopup = false;
                      item.setVisible(false);
                      this.map.removeLayer(this.mdVectorLayer);//锚地图标
                    }
                }
        });
    },

弹窗mapClick

// 弹窗
    mapClick() {
      this.map.on("singleclick", evt => {
        this.isShowSerchList = false;
        let pixel = this.map.getEventPixel(evt.originalEvent);
        let feature = this.map.forEachFeatureAtPixel(
          evt.pixel,
          feature => feature
        );
        if (feature) {
          console.log(feature,"feature")
          this.shipName = feature.values_.shipName; //Feature对象集合中的
          this.portName = feature.values_.portName?feature.values_.portName:feature.values_.name;//港口
          this.portId = feature.values_.portId;
          this.mmsi = feature.values_.mmsi;
          this.nature = feature.values_.nature;
          this.csx = feature.values_.csx;
          this.speed = feature.values_.speed;
          this.updateTime = feature.values_.updateTime;
          this.shipStatus=feature.values_.shipStatus;
          this.vipStatus=feature.values_.vipStatus;
          this.shipType = feature.values_.shipType;
          this.areaName = feature.values_.areaName;
          console.log(this.areaName,"this.areaName");
          this.lonAndLatData = feature.values_.lonAndLatData;
          // 锚地名字
          this.anchorageName = feature.values_.anchorageName;
          console.log(this.anchorageName,"this.anchorageName");
          let coordinates = feature.getGeometry().getCoordinates();
          console.log(coordinates, "coordinates当前坐标");
          this.longitude = coordinates[0];
          this.latitude = coordinates[1];
          // 锚地
          if(this.anchorageName){
            setTimeout(() => {
              this.overlay.setPosition(coordinates);
            }, 0);
          }
          if(this.anchorageName){
            this.shopPopup = true;
          }else{
            this.shopPopup = false;
          }
        } else {
          this.shopPopup = false;
        }
      });
    },

6.mounted数据加载

mounted(){
    this.initMap(); //加载地图
    this.getAnchorageData();//锚地
}

7.锚地数据获取

重要代码

// 获取锚地数据
    getAnchorageData(){
      let arr = this.map.getView().calculateExtent(this.map.getSize());//获取左下角和右上角经纬度
      let params = {
        leftLongitude: arr[0],
        leftLatitude: arr[1],
        rightLongitude: arr[2],
        rightLatitude: arr[3],
      }
      this.mdFeatures = [];
      this.mdMarker = [];
      homePageAnchorageData(params).then(res=>{
        if(res.code == 200){
              //
                //
              this.anchorageFeatures = res.data.map(item=>{
                return item.lonAndLatDatas;
              });
              //取第一个坐标
              const selectOneData = res.data.map(item=>{
                  return item.lonAndLatDatas[0];
              });
              const selectOneName = res.data.map(item=>{
                  return item.anchorageName;
              });
              console.log(selectOneName,"取第一个坐标名字");
              // 添加图标
              this.mdFeatures = selectOneData;
              this.mdFeatures.map((item, index) => {
                  this.mdMarker.push(
                      new Feature({
                        geometry: new Point([item[0], item[1]], "XY"),
                        anchorageName:selectOneName[index],
                        index: index
                      })
                  );
              });
              let mdIconStyles = [];
              this.mdMarker.forEach(item => {
                    mdIconStyles.push(
                        new Style({
                          image: new Icon({
                            src: this.anchorageIcon,
                            scale: 0.6,
                            anchor: [0.5, 0.9],// 偏移的 x 与 y 方向值,注意此值与 Cesium 等GIS库偏向方向正好相反
                          }),
                        
                        })
                    );   
              });
              let mdVectorSource = new SourceVec({
                features: this.mdMarker
              });
              this.mdVectorLayer = new LayerVec({
                name: "mdVectorLayer",
                source: mdVectorSource,
                style: (feature)=> {
                  let iconStyle = mdIconStyles[feature.values_.index];
                  return [iconStyle];
                },
                zIndex: 13
              });
              this.map.addLayer(this.mdVectorLayer);
              this.mdVector = true;
              // this.anchorageFeatures = [
              //   ["113.306100", "29.629998"],
              //   ["113.296623", "29.619303"],
              //   ["113.294041", "29.620805"],
              //   ["113.302937", "29.631876"]
              // ];
              // 画图层
              this.drawSource = new SourceVec({ wrapX: false })
              this.anchorageVectorLayer = new LayerVec({
                name: "anchorageVectorLayer",
                source: this.drawSource,
                style: function (feature) {
                  let styles = [
                    new Style({
                      stroke: new Stroke({
                        width: 2,
                        color: '#ff4e4e'
                      }),
                      fill: new Fill({
                        color: 'rgba(255, 78, 78, 0.2)'
                      }),
                    })
                  ]
                  var geometry = feature.getGeometry()
                  if (geometry instanceof LineString) {
                    geometry.forEachSegment(function (start, end) {
                      console.log(start,"start")
                      styles.push(new Style({
                        geometry: new Point(start),
                        image: new CircleStyle({
                          radius: 4,
                          snapToPixel: false,
                          fill: new Fill({
                            color: 'white'
                          }),
                          stroke: new Stroke({
                            color: '#FF0F0F',
                            width: 2
                          }),
                        })
                      }))
                    })
                  }
                  return styles
                },
                zIndex:12
              });
              this.anchorageFeatures.forEach(item=>{
                this.drawSource.addFeature(new Feature({
                  geometry: new Polygon([item])
                }));
              })
              this.map.addLayer(this.anchorageVectorLayer);
              this.anchorageVector = true;
        }
      })
    },

console.log打印的地方截图:

到此这篇关于Vue结合openlayers按照经纬度坐标实现锚地标记及绘制多边形区域的文章就介绍到这了,更多相关Vue 绘制多边形区域内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯