Leaflet——手动/动态绘制圆,线,多边形(单个及多个)

 

目录

初始化

动态绘圆

动态绘线

 动态绘多边形(单个)

 动态绘多边形(多个)


初始化

<div ref="map" id="map"></div>
#map {
  height: 90%;
  width: 100%;
}
import { ref, onMounted, nextTick } from "vue";
import { Config } from "@/config";//项目配置
//引入leaflet
import L from "leaflet";
import "leaflet/dist/leaflet.css";

//初始化
let map = ref(); //地图容器
let myMap; //地图实例

const initDate = () => {
  myMap = L.map(map.value).setView([31, 117], 13);
  L.tileLayer(Config.baseMap).addTo(myMap);;//项目配置地图接口,没有可以使用下面的在线地图
  //在线的瓦片地图源,"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",需要翻墙
};
onMounted(() => {
  nextTick(() => {
    initDate();
  });
});

动态绘圆

思路:动态绘圆主要涉及到三个事件:mousedown,mousemove,mouseup
mousedown确定圆的圆心,mouseup确定圆的半径,mousemove绘制鼠标移动过程中圆的变化

鼠标按下确定圆心,松开鼠标确定半径绘制完成

import { ref, onMounted, nextTick } from "vue";
import { Config } from "@/config";
import L from "leaflet";
import "leaflet/dist/leaflet.css";

let map = ref(); //地图容器
let myMap; //地图实例

//绘制圆
//读取点击位置坐标并返回其经纬度
//r用来存储半径,i用来存储圆心经纬度
//tempCircle是用来存放圆的图层
let r;
let i;
let tempCircle;
//移除圆图层
function removeCircle() {
  myMap.removeLayer(tempCircle);
}
function drawCircle() {
  //在绘制圆之前需要先判断是否已经绘制过了,如果有,则清空再绘制
  //如果需要绘制多个圆,则不必此句
  if (tempCircle) {
    removeCircle();
  }
  r = 0;
  i = null;
  tempCircle = new L.circle();
  myMap.dragging.disable(); //将mousemove事件拖拽地图禁用
  //监听鼠标落下事件
  myMap.on("mousedown", onmouseDown);
  function onmouseDown(e) {
    //确定圆心
    i = e.latlng;
    //监听鼠标移动事件
    myMap.on("mousemove", onMove);
    //监听鼠标弹起事件
    myMap.on("mouseup", onmouseUp);
  }
  function onMove(e) {
    r = L.latLng(e.latlng).distanceTo(i); //计算半径
    if (i) {
      //绘制圆心位置与半径
      tempCircle.setLatLng(i);
      tempCircle.setRadius(r);
      tempCircle.setStyle({ color: "#ff0000", fillOpacity: 0.5});
      myMap.addLayer(tempCircle);
    }
  }
  function onmouseUp(e) {
    r = L.latLng(e.latlng).distanceTo(i);
    L.circle(i, { radius: r, color: "#ff0000", fillOpacity:0.5 });
    myMap.addLayer(tempCircle);
    myMap.dragging.enable();
    //动画滑动居中圆
    myMap.flyToBounds(tempCircle.getBounds());

    i = null;
    r = 0;
    //取消监听事件
    myMap.off("mousedown");
    myMap.off("mouseup");
    myMap.off("mousemove");
  }
}

const initDate = () => {
  myMap = L.map(map.value).setView([31, 117], 13);
  L.tileLayer(Config.baseMap).addTo(myMap);
  drawCircle();//开始绘制圆时调用,可以反复调用,自动清空
};
onMounted(() => {
  nextTick(() => {
    initDate();
  });
});

动态绘线

思路:动态绘线主要涉及到三个事件:click,dbclick,mousemove
click确定线的折点,dbclick确定线的终点,mousemove绘制鼠标移动过程线的变化

​
<el-button-group style="margin-top: 5px">
          <el-button :icon="Edit" @click="drawLines">开始编辑</el-button>
          <el-button :icon="Close" @click="offDraw">关闭编辑</el-button>
          <el-button :icon="Delete" @click="deleteDraw">清除</el-button>
        </el-button-group>

​
import { ref, onMounted, nextTick } from "vue";
import { Config } from "@/config";
import L from "leaflet";
import "leaflet/dist/leaflet.css";

let map = ref(); //地图容器
let myMap; //地图实例
let points = [];//折点
let lines; //折线
let timer;

//按钮和双击都能结束绘制
//点击按钮结束绘制
const offDraw = () => {
  lines.setLatLngs(points);
  //触发双击事件,结束绘制
  myMap.fire("dblclick");
  myMap.off("dblclick");
};

//清除多边形
const deleteDraw = () => {
  myMap.removeLayer(lines);
};

//开始绘制
function drawLines() {
  if (lines) {
    deleteDraw();
  }
  points = [];
  lines = new L.polyline(points).addTo(myMap); 
  myMap.off("dblclick"); //首次绘制时取消默认双击放大地图事件
  myMap.on("click", onClick);
  function onClick(e) {
    clearTimeout(timer); // 先清定时器
    timer = setTimeout(() => {
      // 再延迟执行
      points.push([e.latlng.lat, e.latlng.lng]);
      lines.setLatLngs(points);
      myMap.on("mousemove", onMove);
      myMap.on("dblclick", onDoubleClick);
    }, 50);
  }
  function onMove(e) {
    points.push([e.latlng.lat, e.latlng.lng]);
    lines.setLatLngs(points);
    points.pop();
  }

  function onDoubleClick(e) {
    clearTimeout(timer);
    myMap.off("click");
    myMap.off("mousemove");
  }
}

const initDate = () => {
  myMap = L.map(map.value).setView([31, 117], 13);
  L.tileLayer(Config.baseMap).addTo(myMap);
  drawLines();
};
onMounted(() => {
  nextTick(() => {
    initDate();
  });
});

 动态绘多边形(单个)

思路:动态绘多边形主要涉及到三个事件:click,dbclick,mousemove
click确定多边形的角,dbclick确定多边形结束的角,mousemove绘制鼠标移动过程中多边形的变化

 注意:单击事件和双击事件冲突,双击时执行两次单击事件;使用定时器解决,在单击事件函数里通过定时器控制延迟执行。单击事件函数和双击事件函数里都先清定时器。

效果:双击第一次点击执行单击函数,第二次点击执行双击函数,达到最后双击结束点也算多边形一角的效果。

​
<el-button-group style="margin-top: 5px">
          //开始编辑单个多边形drawPolygon,多个多边形drawPolygons
          <el-button :icon="Edit" @click="drawPolygon">开始编辑</el-button>
          <el-button :icon="Close" @click="offDraw">关闭编辑</el-button>
          <el-button :icon="Delete" @click="deleteDraw">清除</el-button>
        </el-button-group>

​
import { ref, onMounted, nextTick } from "vue";
import { Config } from "@/config";
//引入leaflet
import L from "leaflet";
import "leaflet/dist/leaflet.css";


let map = ref();
let myMap; 
let points = [];
let polygon;
let timer;
//按钮和双击都能结束绘制
//点击按钮结束绘制
const offDraw = () => {
  polygon.setLatLngs(points);
  //触发双击事件,结束绘制
  myMap.fire("dblclick");
  myMap.off("dblclick");
};
//清除多边形
const deleteDraw = () => {
  myMap.removeLayer(polygon);
};
//开始绘制
function drawPolygon() {
  if (polygon) {
    deleteDraw();
  }
  points = [];
  polygon = new L.polygon(points, { color: "red" }).addTo(myMap);
  //取消默认双击放大地图事件
  myMap.off("dblclick"); 
  myMap.on("click", onClick);
  function onClick(e) {
    // 先清定时器
    clearTimeout(timer); 
    timer = setTimeout(() => {
      // 再延迟执行
      points.push([e.latlng.lat, e.latlng.lng]);
      polygon.setLatLngs(points);
      myMap.on("mousemove", onMove);
      myMap.on("dblclick", onDoubleClick);
      console.log("click", polygon._latlngs[0]);
    }, 50);
  }
  function onMove(e) {
    points.push([e.latlng.lat, e.latlng.lng]);
    polygon.setLatLngs(points);
    points.pop();
  }

  function onDoubleClick(e) {
    clearTimeout(timer);
    myMap.off("click");
    myMap.off("mousemove");
  }
//初始化
const initDate = () => {
  myMap = L.map(map.value).setView([31, 117], 13);
  L.tileLayer(Config.baseMap).addTo(myMap);
  drawPolygon();//开始绘制多边形
};
onMounted(() => {
  nextTick(() => {
    initDate();
  });
});

 动态绘多边形(多个)

import { ref, onMounted, nextTick } from "vue";
import { Config } from "@/config";
import L from "leaflet";
import "leaflet/dist/leaflet.css"; 

let map = ref(); //地图容器
let myMap; //地图实例
let points = [];
let polygon;
let polygonGroup;
let timer;

//按钮和双击都能结束绘制
//点击按钮结束绘制
const offDraw = () => {
  polygon.setLatLngs(points);
  //触发双击事件,结束绘制
  myMap.fire("dblclick");
  myMap.off("click");
  myMap.off("dblclick");
};
//清除多边形图层组
const deleteDraw = () => {
  myMap.removeLayer(polygonGroup);
};
//开始绘制
function drawPolygons() {
  if (polygonGroup) {
    deleteDraw();
  }
  points = [];
  polygon = new L.polygon(points, { color: "red" });
  polygonGroup = L.layerGroup().addTo(myMap);
  polygonGroup.addLayer(polygon);
  myMap.off("dblclick"); //首次绘制时取消默认双击放大地图事件
  myMap.on("click", onClick);
  function onClick(e) {
    clearTimeout(timer); // 先清定时器
    timer = setTimeout(() => {
      // 再延迟执行
      points.push([e.latlng.lat, e.latlng.lng]);
      polygon.setLatLngs(points);
      myMap.on("mousemove", onMove);
      myMap.on("dblclick", onDoubleClick);
    }, 10);
  }
  function onMove(e) {
    points.push([e.latlng.lat, e.latlng.lng]);
    polygon.setLatLngs(points);
    points.pop();
  }

  function onDoubleClick(e) {
    clearTimeout(timer);
    myMap.off("mousemove");
    points = [];
    polygon = new L.polygon(points, { color: "red" }).addTo(polygonGroup);
  }
}

const initDate = () => {
  myMap = L.map(map.value).setView([31, 117], 13);
  L.tileLayer(Config.baseMap).addTo(myMap);
  drawPolygons();
};
onMounted(() => {
  nextTick(() => {
    initDate();
  });
});

 

在 Vue.js 中使用 Leaflet 地图库手动绘制多边形并获取其经纬度数组,你可以按照以下步骤操作: 1. 首先,确保已经在项目中安装了 Vue 和 Leaflet。可以使用 Vue CLI 或手动引入 CDN。 2. 引入依赖: ```html <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" /> ``` 3. 在组件里创建一个 Map 组件并初始化 Leaflet 地图: ```js <template> <div id="map-container"> <div ref="map" style="height: 500px; width: 100%"></div> </div> </template> <script> import L from 'leaflet'; export default { data() { return { map: null, markers: [], polygon: null, coordinates: [] }; }, mounted() { this.initMap(); }, methods: { initMap() { this.map = L.map('map-container').setView([51.505, -0.09], 13); // 设置初始中心点和缩放级别 L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors', maxZoom: 18, }).addTo(this.map); // 添加点击事件监听器,用于画线 this.map.on('click', (e) => { const latlng = e.latlng; if (!this.polygon) { this.polygon = new L.Polygon([latlng], { color: 'red' }); this.map.addLayer(this.polygon); this.coordinates.push(latlng); } else { this.polygon.setLatLngs([...this.coordinates, latlng]); this.coordinates.push(latlng); } }); }, getPolygonCoordinates() { return this.coordinates; } } }; </script> ``` 在这个例子中,当你点击地图时会添加一个新的顶点到多边形,直到形成一个完整的闭合路径。`getPolygonCoordinates` 方法会在多边形绘制完成后返回所有的经纬度数组。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值