Vue工程搭建Leaflet项目第三弹:绘制几何对象(点、线、面)

7 篇文章 5 订阅
4 篇文章 0 订阅

前言

在leaflet中绘制几何对象很简单,通过鼠标单击事件、移动事件获取地图坐标并存储到几何对象中,通过双击事件或者右键事件结束绘制。可以通过添加已经实现了的绘制插件完成,也可以自定义绘制事件绘制几何对象。

地图事件应该写为方法的形式,不然关闭绘制点事件的时候会关闭绘制线和面的事件。同理,线和面也如此

一、自定义事件绘制

(1)绘制点

    pointClick() {
      if (this.isPointClicked) {
        // 第二次点击的时候退出绘制
        this.isPointClicked = false;
        return;
      }
      this.isPointClicked = true;
      this.isPolylineClicked = false;
      this.isPolygonClicked = false;
      if (window._map) {
        this.map = window._map;
        // 关闭地图双击事件
        this.map.doubleClickZoom.disable();
      }
      if (this.isPointClicked) {
        this.setCursor("crosshair");
      }
      console.log(window._map);
      const circleOption = {
        radius: 10,
        fill: true,
        color: "red",
        weight: 3.5, // 边线宽度:单位像素值
        opacity: 1, // 边线透明度
        fillColor: "red",
        fillOpacity: 1 // 最好设置透明度,默认值0.2
      };
      const onClick = evt => {
        console.log(evt.latlng);
        L.circle(evt.latlng, circleOption).addTo(this.map);
      };
      this.map.on("click", onClick);
      this.map.on("dblclick", () => {
        // 关闭单击事件
        this.map.off({ click: onClick });
        this.setCursor("pointer");
        // 开启双击事件
        this.map.doubleClickZoom.enable();
      });
    },

(2)绘制线

    polylineClick() {
      if (this.isPolylineClicked) {
      	// 第二次点击的时候退出绘制
        this.isPolylineClicked = false;
        return;
      }
      this.isPolylineClicked = true;
      this.isPointClicked = false;
      this.isPolygonClicked = false;

      if (window._map) {
        this.map = window._map;
        // 关闭地图双击事件
        this.map.doubleClickZoom.disable();
      }
      if (this.isPolylineClicked) {
        this.setCursor("crosshair");
      }
      const latlngs = [];
      // circle 样式
      const circleOption = {
        radius: 10,
        fill: true,
        color: "#ffb61e",
        weight: 3.5, // 边线宽度:单位像素值
        opacity: 1, // 边线透明度
        fillColor: "blue",
        fillOpacity: 1 // 最好设置透明度,默认值0.2
      };

      // 线段样式
      const polylineOption = {
        stroke: true, // 开启路径追踪,默认为true
        color: "yellow"
      };
      // 绘制线段
      const polyline = L.polyline(latlngs, polylineOption);
      // 临时线段
      const tempLine = L.polyline([], polylineOption);
      console.log(tempLine);
      const onClick = evt => {
        latlngs.push([evt.latlng.lat, evt.latlng.lng]);
        const circle = L.circle(evt.latlng, circleOption);
        circle.addTo(this.map);
        polyline.addLatLng(evt.latlng);
        polyline.addTo(this.map);
      };
      this.map.on("click", onClick);
      const onMouseMove = evt => {
        if (latlngs.length > 0) {
          // 添加临时线段
          const coords = [
            latlngs[latlngs.length - 1],
            [evt.latlng.lat, evt.latlng.lng]
          ];
          tempLine.setLatLngs(coords);
          this.map.addLayer(tempLine);
        }
      };
      this.map.on("mousemove", onMouseMove);

      // 双击结束绘制
      this.map.on("dblclick", () => {
        // 关闭单击事件
        this.map.off({ click: onClick, mousemove: onMouseMove });
        this.setCursor("pointer");
        // 开启双击事件
        this.map.doubleClickZoom.enable();
      });
    },

(3)绘制面

   polygonClick() {
      if (this.isPolygonClicked) {
      	// 第二次点击的时候退出绘制
        this.isPolygonClicked = false;
        return;
      }
      this.isPolygonClicked = true;
      this.isPointClicked = false;
      this.isPolylineClicked = false;
      if (!this.isPolygonClicked) {
        return;
      }
      if (window._map) {
        this.map = window._map;
        // 关闭地图双击事件
        this.map.doubleClickZoom.disable();
      }
      if (this.isPolygonClicked) {
        this.setCursor("crosshair");
      }
      const latlngs = [];
      // circle 样式
      const circleOption = {
        radius: 10,
        fill: true,
        color: "#ffb61e",
        weight: 3.5, // 边线宽度:单位像素值
        opacity: 1, // 边线透明度
        fillColor: "blue",
        fillOpacity: 1 // 最好设置透明度,默认值0.2
      };

      // 线段样式
      const polylineOption = {
        stroke: true, // 开启路径追踪,默认为true
        color: "yellow"
      };
      const polyline = L.polyline(latlngs, polylineOption);
      const tempLine = L.polyline([], polylineOption);
      const polygon = L.polygon(latlngs, polylineOption);
      const onClick = evt => {
        latlngs.push([evt.latlng.lat, evt.latlng.lng]);
        L.circle(evt.latlng, circleOption).addTo(this.map);
        polyline.addLatLng(evt.latlng);
        polyline.addTo(this.map);
        polygon.addLatLng(evt.latlng);
        polygon.addTo(this.map);
      };
      this.map.on("click", onClick);
      const onMouseMove = evt => {
      	// 至少有一个点才添加临时线段
        if (latlngs.length > 0) {
          //面的临时线段坐标顺序[起点,鼠标移动点,最后一次点击点]
          tempLine.setLatLngs([
            latlngs[0],
            evt.latlng,
            latlngs[latlngs.length - 1]
          ]);
          //tempLine.setLatLngs([[latlngs[0],]])
          tempLine.addTo(this.map);
          polygon.setLatLngs([...latlngs, evt.latlng]);
        }
      };
      this.map.on("mousemove", onMouseMove);

      this.map.on("dblclick", () => {
        // 关闭单击事件
        this.map.off({ click: onClick, mousemove: onMouseMove });
        this.setCursor("pointer");
        // 开启双击事件
        this.map.doubleClickZoom.enable();
      });
    },

二、添加绘制插件

emoji

三、完整代码

<template>
  <div class="toolbar-container">
    <button :class="isPointClicked?'active':''" @click="pointClick"></button>
    <button :class="isPolylineClicked?'active':''" @click="polylineClick">线</button>
    <button :class="isPolygonClicked?'active':''" @click="polygonClick"></button>
    <button @click="clearAll">清除</button>
  </div>
</template>

<script>
import L from "leaflet";
export default {
  name: "ToolBar",
  components: {},
  data() {
    return {
      map: undefined,
      isPointClicked: false,
      isPolylineClicked: false,
      isPolygonClicked: false,
      isClear: false
    };
  },
  watch: {
    isPointClicked(val) {
      if (!val) {
        // 清除监听事件
        // this.map.clearAllEventListeners();
      }
    },
    isPolylineClicked(val) {
      if (!val) {
        // 清除监听事件
        //this.map.clearAllEventListeners();
      }
    },
    isPolygonClicked(val) {
      if (!val) {
        // 清除监听事件
        // this.map.clearAllEventListeners();
      }
    }
  },
  created() {
    //console.log("aaaaaa")
  },
  methods: {
  // 地图事件应该写为方法的形式,不然关闭绘制点事件的时候会关闭绘制线和面的事件。同理,线和面也如此
    pointClick() {
      if (this.isPointClicked) {
        this.isPointClicked = false;
        return;
      }
      this.isPointClicked = true;
      this.isPolylineClicked = false;
      this.isPolygonClicked = false;
      if (window._map) {
        this.map = window._map;
        // 关闭地图双击事件
        this.map.doubleClickZoom.disable();
      }
      if (this.isPointClicked) {
        this.setCursor("crosshair");
      }
      console.log(window._map);
      const circleOption = {
        radius: 10,
        fill: true,
        color: "red",
        weight: 3.5, // 边线宽度:单位像素值
        opacity: 1, // 边线透明度
        fillColor: "red",
        fillOpacity: 1 // 最好设置透明度,默认值0.2
      };

      const onClick = evt => {
        console.log(evt.latlng);
        L.circle(evt.latlng, circleOption).addTo(this.map);
      };
      this.map.on("click", onClick);
      this.map.on("dblclick", () => {
        // 关闭单击事件
        this.map.off({ click: onClick });
        this.setCursor("pointer");
        // 开启双击事件
        this.map.doubleClickZoom.enable();
      });
    },
    polylineClick() {
      if (this.isPolylineClicked) {
        this.isPolylineClicked = false;
        return;
      }
      this.isPolylineClicked = true;
      this.isPointClicked = false;
      this.isPolygonClicked = false;

      if (window._map) {
        this.map = window._map;
        // 关闭地图双击事件
        this.map.doubleClickZoom.disable();
      }
      if (this.isPolylineClicked) {
        this.setCursor("crosshair");
      }
      const latlngs = [];
      // circle 样式
      const circleOption = {
        radius: 10,
        fill: true,
        color: "#ffb61e",
        weight: 3.5, // 边线宽度:单位像素值
        opacity: 1, // 边线透明度
        fillColor: "blue",
        fillOpacity: 1 // 最好设置透明度,默认值0.2
      };

      // 线段样式
      const polylineOption = {
        stroke: true, // 开启路径追踪,默认为true
        color: "yellow"
      };
      // 绘制线段
      const polyline = L.polyline(latlngs, polylineOption);
      // 临时线段
      const tempLine = L.polyline([], polylineOption);
      console.log(tempLine);
      const onClick = evt => {
        latlngs.push([evt.latlng.lat, evt.latlng.lng]);
        const circle = L.circle(evt.latlng, circleOption);
        circle.addTo(this.map);
        polyline.addLatLng(evt.latlng);
        polyline.addTo(this.map);
      };
      this.map.on("click", onClick);
      const onMouseMove = evt => {
        // 至少有一个点才添加临时线段
        if (latlngs.length > 0) {
          // 添加临时线段
          const coords = [
            latlngs[latlngs.length - 1],
            [evt.latlng.lat, evt.latlng.lng]
          ];
          tempLine.setLatLngs(coords);
          this.map.addLayer(tempLine);
        }
      };
      this.map.on("mousemove", onMouseMove);

      // 双击结束绘制
      this.map.on("dblclick", () => {
        // 关闭单击事件
        this.map.off({ click: onClick, mousemove: onMouseMove });
        this.setCursor("pointer");
        // 开启双击事件
        this.map.doubleClickZoom.enable();
      });
    },
    polygonClick() {
      if (this.isPolygonClicked) {
        this.isPolygonClicked = false;
        return;
      }
      this.isPolygonClicked = true;
      this.isPointClicked = false;
      this.isPolylineClicked = false;
      if (!this.isPolygonClicked) {
        return;
      }
      if (window._map) {
        this.map = window._map;
        // 关闭地图双击事件
        this.map.doubleClickZoom.disable();
      }
      if (this.isPolygonClicked) {
        this.setCursor("crosshair");
      }
      const latlngs = [];
      // circle 样式
      const circleOption = {
        radius: 10,
        fill: true,
        color: "#ffb61e",
        weight: 3.5, // 边线宽度:单位像素值
        opacity: 1, // 边线透明度
        fillColor: "blue",
        fillOpacity: 1 // 最好设置透明度,默认值0.2
      };

      // 线段样式
      const polylineOption = {
        stroke: true, // 开启路径追踪,默认为true
        color: "yellow"
      };
      const polyline = L.polyline(latlngs, polylineOption);
      const tempLine = L.polyline([], polylineOption);
      const polygon = L.polygon(latlngs, polylineOption);
      const onClick = evt => {
        latlngs.push([evt.latlng.lat, evt.latlng.lng]);
        L.circle(evt.latlng, circleOption).addTo(this.map);
        polyline.addLatLng(evt.latlng);
        polyline.addTo(this.map);
        polygon.addLatLng(evt.latlng);
        polygon.addTo(this.map);
      };
      this.map.on("click", onClick);
      const onMouseMove = evt => {
        // 至少有一个点才添加临时线段
        if (latlngs.length > 0) {
          //面的临时线段坐标顺序[起点,鼠标移动点,最后一次点击点]
          tempLine.setLatLngs([
            latlngs[0],
            evt.latlng,
            latlngs[latlngs.length - 1]
          ]);
          //tempLine.setLatLngs([[latlngs[0],]])
          tempLine.addTo(this.map);
          polygon.setLatLngs([...latlngs, evt.latlng]);
        }
      };
      this.map.on("mousemove", onMouseMove);

      this.map.on("dblclick", () => {
        // 关闭单击事件
        this.map.off({ click: onClick, mousemove: onMouseMove });
        this.setCursor("pointer");
        // 开启双击事件
        this.map.doubleClickZoom.enable();
      });
    },
    // 设置鼠标状态
    setCursor(state) {
      if (this.map) {
        this.map._container.style.cursor = state;
      }
    },

    // 清除图形
    clearAll() {
      this.isPointClicked = false;
      this.isPolylineClicked = false;
      this.isPolygonClicked = false;
      if (this.map) {
        this.map.eachLayer(layer => {
          if (!layer.options.layerName) {
            // debugger;
            layer.remove();
          }
        });
      }
    }
  }
};
</script>

<style lang="scss" scoped>
.toolbar-container {
  position: absolute;
  top: 100px;
  margin-left: 10px;
  z-index: 9999;
  button {
    display: block;
    width: 35px;
    height: 35px;
    border: none;
    border: 1px solid #ddd;
    border-bottom: none;
    cursor: pointer;
    &:hover {
      background: #ddd;
    }
  }
  button:last-child {
    border-bottom: 1px solid #ddd;
  }
}
.active {
  background: #ddd;
}
/deep/.el-button + .el-button {
  margin-left: 0;
}
</style>>

四、页面展示

在这里插入图片描述

欢迎大家关注我的公众号,我也会在公众号同步更新。

若大家对进阶打怪有兴趣的话,欢迎订阅以下专栏

地址:WebGIS入门和进阶实战

项目地址,请查阅

地址:leaflet-app

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值