openlayers Draw Modify Snap

功能介绍:
1. 使用Draw进行绘画多边形
2. 点击多边形边框 使用 Modify 功能
3. 点击右键进行清除Draw功能
4. 键盘使用Ctrl+Z对Draw和Modify添加撤回功能

// HTML:
<template>
  <div id="map" ref="rootmap"></div>
</template>

<script>
import "ol/ol.css";
import { Map, View, Feature } from "ol";
import mapconfig from "./config.js";
import { Draw, Snap, Modify, DragPan } from "ol/interaction";
import { Vector as VectorSource } from "ol/source";
import { Vector as VectorLayer } from "ol/layer";
import { Circle as CircleStyle, Fill, Stroke, Style } from "ol/style";
import { MultiPoint } from "ol/geom";

export default {
  data() {
    return {
      map: null,
      sourceDraw: null,
      layerDraw: null,
      draw: null,
      snap: null,
      modify: null,
      pan: null,
      feature: null,
      undoStack: [],
      flag: false
    };
  },
  mounted() {
    var mapcontainer = this.$refs.rootmap;
    this.map = new Map({
      target: mapcontainer,
      layers: mapconfig.layers,
      view: new View({
        center: mapconfig.center,
        zoom: mapconfig.zoom
      })
    });
    // 创建绘画图层
    this.sourceDraw = new VectorSource();
    this.layerDraw = new VectorLayer({
      source: this.sourceDraw,
      style: [
        new Style({
          fill: new Fill({
            color: "rgba(225, 225, 225, .5)"
          }),
          stroke: new Stroke({
            color: "#ff0000",
            width: 3
          })
        }),
        new Style({
          image: new CircleStyle({
            radius: 5,
            fill: new Fill({
              color: "red"
            })
          }),
          geometry: function(feature) {
            var coordinates = feature.getGeometry().getCoordinates()[0];
            return new MultiPoint(coordinates);
          }
        })
      ]
    });
    this.map.addLayer(this.layerDraw);

    // 绘画功能
    this.drawFn();

    // 修改功能
    this.modifyFn();
    this.modify.on("modifystart", this.modifyStartFn);
    this.modify.on("modifyend", this.modifyEndFn);

    // 吸附功能
    this.snapFn();

    // 地图拖动
    this.panFn();

    // 地图左键点击
    this.map.on("click", this.mapClickFn);
    // 地图右键点击
    this.map.on("contextmenu", this.mapContextmenuFn);
    // 地图键盘事件监听
    document.onkeydown = this.mapOnkeydownFn;
  },
  methods: {
    drawFn() {
      this.draw = new Draw({
        source: this.sourceDraw,
        type: "Polygon",
        stopClick: true,
        snapTolerance: 1,
        condition: function(e) {
          // 按钮配置,左键点击
          if (e.originalEvent.buttons === 1) {
            return true;
          } else {
            return false;
          }
        }
      });

      this.draw.on("drawstart", this.drawStartFn);
      this.draw.on("drawend", this.drawEndFn);
      this.map.addInteraction(this.draw);
    },
    // 绘画前
    drawStartFn(e) {
      this.pan.setActive(false);
      this.modify.setActive(false);
    },
    // 绘画后
    drawEndFn(e) {
      this.pan.setActive(true);
      this.modify.setActive(true);
    },
    // 屏蔽绘画
    removeDrawFn() {
      this.draw.setActive(false);
      this.map.removeInteraction(this.draw);
    },

    // 修改功能初始化
    modifyFn() {
      this.modify = new Modify({
        source: this.sourceDraw,
        pixelTolerance: 4
      });
      this.map.addInteraction(this.modify);
    },
    // 修改前
    modifyStartFn(e) {
      this.pan.setActive(false);
      this.removeDrawFn();

      var item = e.features.array_[0];
      this.feature = new Feature();
      this.feature.setGeometry(item.getGeometry().clone());
      this.feature.setGeometryName(item.getGeometryName());
      this.feature.setStyle(item.getStyle());
      this.feature.ol_uid = item.ol_uid;
      this.undoStack.push(this.feature);
    },
    // 修改后
    modifyEndFn(e) {
      this.pan.setActive(true);
      setTimeout(() => {
        this.removeDrawFn();
        this.drawFn();
      }, 200);
    },

    // 吸附功能
    snapFn() {
      this.snap = new Snap({
        source: this.sourceDraw,
        pixelTolerance: 4
      });
    },

    // 地图拖动
    panFn() {
      this.map.getInteractions().forEach((element, index, array) => {
        if (element instanceof DragPan) {
          this.pan = element;
        }
      });
    },

    // 左键点击
    mapClickFn(e) {
      if (this.flag) {
        this.removeDrawFn();
        this.drawFn();
      } else {
        this.flag = false;
      }
    },

    // 右键点击
    mapContextmenuFn(e) {
      e.preventDefault();
      this.flag = true;
      this.removeDrawFn();
      this.pan.setActive(true);
      this.modify.setActive(true);
    },

    // 键盘事件监听
    mapOnkeydownFn(e) {
      if (e.keyCode == 27) {
        // ESC键盘点击,绘画清空
        this.draw.abortDrawing();
      } else if (e.keyCode == 90 && e.ctrlKey) {
        this.draw.removeLastPoint();
        if (this.undoStack.length !== 0) {
          this.undoClick();
        }
      }
    },

    // 撤回上一步修改操作
    undoClick() {
      let feature = this.undoStack.pop();
      let findFeatureByUid1 = this.findFeatureByUid(feature.ol_uid);
      this.sourceDraw.removeFeature(findFeatureByUid1);
      this.sourceDraw.addFeature(feature);
    },
    findFeatureByUid(uid) {
      let featureByUid = this.sourceDraw.getFeatureByUid(uid);
      return featureByUid;
    }
  }
};
</script>

<style scoped>
#map {
  height: 100vh;
}
/*隐藏ol的一些自带元素*/
.ol-attribution,
.ol-zoom {
  display: none;
}
</style>
/**
'EPSG:4326'-经纬度坐标-WGS84
'EPSG:3857'- xy坐标-web墨卡托
 */
import TileLayer from "ol/layer/Tile"
import TileGrid from "ol/tilegrid/TileGrid"
import proj4 from 'proj4' 
import {register} from 'ol/proj/proj4'
import TileImage from 'ol/source/TileImage'
import { fromLonLat } from "ol/proj";


proj4.defs("EPSG:4008", "+proj=longlat +ellps=clrk66 +no_defs")
proj4.defs("BD-MC", "+proj=merc +lon_0=0 +units=m +ellps=clrk66 +no_defs")
register(proj4)

var streetmap=function(){
    var baiduMapLayer=null;

  // 自定义分辨率和瓦片坐标系
  let resolutions = [];
  let maxZoom = 18;
  // 计算百度使用的分辨率
  for (let i = 0; i <= maxZoom; i++) {
    resolutions[i] = Math.pow(2, maxZoom - i);
  }
  let tilegrid = new TileGrid({
    origin: [0, 0], // 设置原点坐标
    resolutions: resolutions // 设置分辨率
  });
  // 创建百度地图的数据源
  let baiduSource = new TileImage({
    projection: "BD-MC",
    tileGrid: tilegrid,
    tileUrlFunction: function(tileCoord, pixelRatio, proj) {
      let z = tileCoord[0];
      let x = tileCoord[1];
      let y = tileCoord[2] + 1;
      // 百度瓦片服务url将负数使用M前缀来标识
      if (x < 0) {
        x = "M" + -x;
      }
      y = -y;
      if (y < 0) {
        y = "M" + -y;
      }
      let num = Math.ceil(Math.random() * 3);
      return (
        "http://maponline" +
        num +
        ".bdimg.com//onlinelabel/?qt=vtile&x=" +
        x +
        "&y=" +
        y +
        "&z=" +
        z +
        "&styles=pl&udt=20200211&scaler=1&p=0"
      );
    }
  });
  // 百度地图层
  baiduMapLayer = new TileLayer({
    source: baiduSource
  });
  return baiduMapLayer;
}

const baiduMapLayer = streetmap();


var mapconfig = {
  center: fromLonLat([116.40,40]),
  zoom: 10,
  layers: [baiduMapLayer],
};

export default mapconfig;
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值