Vue 绘制多边形区域

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

Vue 绘制多边形区域

船长在船上   2022-09-29 我要评论

前言

本文介绍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打印的地方截图:

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们