vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue 绘制多边形区域

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

作者:船长在船上

OpenLayers是一个用于开发WebGIS客户端的JavaScript包,最初基于BSD许可发行。OpenLayers是一个开源的项目,其设计之意是为互联网客户端提供强大的地图展示功能,包括地图数据显示与相关操作,并具有灵活的扩展机制

前言

本文介绍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 绘制多边形区域内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文