《Leaflet 进阶知识点》- Leaflet.draw 交互绘制

一、安装

使用插件 Leaflet.drawinstall

npm i leaflet-draw

二、 Vue 中引入

<script> 中引入 js

import 'leaflet-draw'

<style> 中引入 css

@import '~leaflet-draw/dist/leaflet.draw.css'

三、初始化

//初始化绘制控件
this.drawControl = new L.Control.Draw({
    position: 'topright',//控件位置 'topleft'(默认), 'topright', 'bottomleft' or 'bottomright'
    draw: {
        polyline: true,
        polygon: true,
        rectangle: true,
        circle: true,
        marker: true,
    }
})
//.addTo(this.map);// 要添加到 L.map 对象中
// 添加绘制完监听事件
this.map.on(L.Draw.Event.CREATED, this.drawCreatedBack);

知识点:

1. 代码第 3 行,设置控件位置,有4个选项,'topleft', 'topright', 'bottomleft' or 'bottomright',默认为 topleft;

2. 代码第 5 - 9 行,设置可绘制的类型,其中 marker 为点;

3. 代码第 12 行, addTo 可不添加。然后自定义样式,启动绘制;

4. 代码第 14 行,地图容器监听绘制完成事件,第二个参数为回调。如果取消监听,第二个参数要一样,如下:

this.container.map.off(L.Draw.Event.CREATED, this.drawCreatedBack);

四、启动绘制

switch (idx) {
    case 0: {// 点
        this.drawObj = new L.Draw.Marker(this.map, this.drawControl.options.draw.marker);
        break;
    }
    case 1: {// 圆
        this.drawObj = new L.Draw.Circle(this.map, this.drawControl.options.draw.circle);
        break;
    }
    case 2: {// 线
        this.drawObj = new L.Draw.Polyline(this.map, this.drawControl.options.draw.polyline);
        break;
    }
    case 3: {// 矩形
        this.drawObj = new L.Draw.Rectangle(this.map, this.drawControl.options.draw.rectangle);
        break;
    }
    case 4: {// 多边形
        this.drawObj = new L.Draw.Polygon(this.map, this.drawControl.options.draw.polygon);
        break;
    }                    
}
// 启动 
this.drawObj.enable();

知识点:

1. drawObj 是绘制对象,有点、线、圆、矩形、多边形;

2. drawControl 是初始化中 new 的 L.Control.Draw 控件对象;

3. 最后一行,也是最关键的,一定要 enable 启动绘制;

五、取消绘制

this.drawObj.disable();

六、绘制完成回调

// 交互绘制回调
drawCreatedBack(e) {
    // 绘制的图形图层对象
    let drawLayer = e.layer;
    // 判断当前没有图层组,需先添加
    if(!this.drawLayerGrounp) {
        //图层组
        this.drawLayerGrounp = new L.FeatureGroup();
        // 添加
        this.map.addLayer(this.drawLayerGrounp);
    }
    // 添加到图层组
    this.drawLayerGrounp.addLayer(drawLayer);
}

知识点:

1. 代码第 4 行,返回绘制的图层对象,如 L.polylineL.polygon等;

2. 代码第 6 - 11 行,将绘制的图层对象添加到图层组中;

3、代码第 13 行,注意是把绘制的图层对象添加到图层组中;

七、清除绘制

//清除绘制
stopDraw() {
    // 删除全部绘制的图层
    if(this.drawLayerGrounp) {
        this.drawLayerGrounp.clearLayers();
    }
    // 取消绘制操作
    this.drawObj.disable();
}

八、销毁

// 销毁绘制控件
destoryDrawCtr() {
    // L.Control.Draw 控件对象
    this.drawControl = null;
    // 绘制对象
    this.drawObj = null;
    // 删除全部绘制的图层
    if(this.drawLayerGrounp) {
        this.drawLayerGrounp.clearLayers();
    }
    // 取消绘制完监听事件,避免在真正开发中,其它地方也监听了 CREATED 事件
    this.container.map.off(L.Draw.Event.CREATED, this.drawCreatedBack);
}

九、效果

十、全部源码

<template>
    <div>
        <div id="map" class="map-main"></div>
        <div class="btn-list">
            <button @click="initDrawCtrl">初始化绘制控件</button><br>
            <button @click="destoryDrawCtr">销毁绘制控件</button><br>
            <button @click="startDraw(0)">点</button>
            <button @click="startDraw(1)">圆</button>
            <button @click="startDraw(2)">线</button>
            <button @click="startDraw(3)">矩形</button>
            <button @click="startDraw(4)">多边形</button>
            <button @click="stopDraw">清除</button>
        </div>
    </div>
</template>

<script>
import 'leaflet'
import 'leaflet-draw'
import '../../public/js/leaflet.draw-cn.js'

export default {
    data() {
        return {
            // L.map 对象
            map: null,
            // L.Control.Draw 控件对象
            drawControl: null,
            // 绘制对象
            drawObj: null,
            // 图形图层组
            drawLayerGrounp: null
        }
    },
    methods: {
        // 启动绘制
        startDraw(idx) {
            // 先取消
            if(this.drawObj) {
                this.drawObj.disable();
            }
            switch (idx) {
                case 0: {// 点
                    this.drawObj = new L.Draw.Marker(this.map, this.drawControl.options.draw.marker);
                    break;
                }
                case 1: {// 圆
                    this.drawObj = new L.Draw.Circle(this.map, this.drawControl.options.draw.circle);
                    break;
                }
                case 2: {// 线
                    this.drawObj = new L.Draw.Polyline(this.map, this.drawControl.options.draw.polyline);
                    break;
                }
                case 3: {// 矩形
                    this.drawObj = new L.Draw.Rectangle(this.map, this.drawControl.options.draw.rectangle);
                    break;
                }
                case 4: {// 多边形
                    this.drawObj = new L.Draw.Polygon(this.map, this.drawControl.options.draw.polygon);
                    break;
                }                    
            }
            // 启动 
            this.drawObj.enable();
        },
        //清除绘制
        stopDraw() {
            // 删除全部绘制的图层
            if(this.drawLayerGrounp) {
                this.drawLayerGrounp.clearLayers();
            }
            // 取消绘制操作
            this.drawObj.disable();
        },
        // 初始化地图
        ininMap() {
            // 初始化地图容器并显天地图
            this.map = L.map('map', {
                //参考坐标系
                crs: L.CRS.EPSG4326,
                //不添加属性说明控件
                attributionControl: false,
                //限制显示地理范围
                maxBounds: L.latLngBounds(L.latLng(-180, -180), L.latLng(180, 180)),
            });

            // 设置范围(这里是武汉)
            this.map.setView([30.59, 114.32], 10);
            // 矢量图+注记
            // let mapTypes = ['vec_c', 'cva_c'];  
            // 影像图+注记
            let mapTypes = ['img_c', 'cia_c']; 
            // 天地图 token
            let tdtToken = 'xxxxxxxxxxxxxxxx';
            let layers = [];
            for(let i = 0, len = mapTypes.length; i < len; i++) {
                let tdtUrl = `http://t0.tianditu.gov.cn/DataServer?T=${mapTypes[i]}&x={x}&y={y}&l={z}&tk=${tdtToken}`;
                let layer = L.tileLayer(tdtUrl, {
                    zoomOffset: 1,
                    noWrap: true,
                    bounds: [[-90, -180], [90, 180]]
                });
                layers.push(layer);
            }
            L.layerGroup(layers).addTo(this.map);
        },
        // 交互绘制回调
        drawCreatedBack(e) {
            console.log('绘制完成', e);
            // 绘制的图形图层对象
            let drawLayer = e.layer;
            // 判断当前没有图层组,需先添加
            if(!this.drawLayerGrounp) {
                //图层组
                this.drawLayerGrounp = new L.FeatureGroup();
                // 添加
                this.map.addLayer(this.drawLayerGrounp);
            }
            // 添加到图层组
            this.drawLayerGrounp.addLayer(drawLayer);
        },
        // 初始化绘制控件
        initDrawCtrl() {
            //初始化绘制控件
            this.drawControl = new L.Control.Draw({
                position: 'topright',//控件位置 'topleft'(默认), 'topright', 'bottomleft' or 'bottomright'
                draw: {
                    polyline: true,
                    polygon: true,
                    rectangle: true,
                    circle: true,
                    marker: true,
                }
            }).addTo(this.map);// 要添加到 L.map 对象中
            // 添加绘制完监听事件
            this.map.on(L.Draw.Event.CREATED, this.drawCreatedBack);
        },
        // 销毁绘制控件
        destoryDrawCtr() {
            // L.Control.Draw 控件对象
            this.drawControl = null;
            // 绘制对象
            this.drawObj = null;
            // 删除全部绘制的图层
            if(this.drawLayerGrounp) {
                this.drawLayerGrounp.clearLayers();
            }
            // 取消绘制完监听事件,避免在真正开发中,其它地方也监听了 CREATED 事件
            this.container.map.off(L.Draw.Event.CREATED, this.drawCreatedBack);
        }
    },
    mounted() {
        // 初始化地图
        this.ininMap();
        // 初始化绘制控件
        this.initDrawCtrl();
    }
}
</script>

<style lang="stylus" scoped>
@import '~leaflet/dist/leaflet.css'
@import '~leaflet-draw/dist/leaflet.draw.css'
.map-main {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: #CCC;
}
.btn-list {
    z-index: 2000;
    position: absolute;
    top: 2px;
    left: 80px;
}
</style>

注意插件默认语言是英文,可参考此篇做中英文转换:

 《Leaflet 进阶知识点》- Leaflet.draw 中英文转换

  • 21
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值