Leafletjs--点、线、多边形的绘制

Leafletjs 学习

最近做的项目很大部分的需求都是和室内地图相关的,学习一下。

gif 图片加载偏慢,再吐槽一下,做个生成目录就那么难吗?

0. 其它

  • 链接:vue移动端商城实战项目

  • 链接:百度地图--点聚合 + 弹窗事件

  • 链接:Leafletjs 官网

  • 参考:Leafletjs参考学习的文章(4星半)

  • 参考:leaflet 自定义 Marker(4星)

1. 关于地图控件

  • 百度地图、高德地图等在室内地图方面都不是很友好,这也是绝大部分地图控件的问题,着重的问题是没有办法让使用系统的用户自己添加自己的地图,可能有其它的技术,但是我不知道啊~;

  • 关于室内地图,3D效果的地图是比较好的,但是我也还没有接触到,而且好像也没有比较好的学习路子,找到的所有能做室内3D地图的都是收费的,这里重点指的是所有。想要自己做的话,可能要用canvas+D3js+Treejs之类的,比较麻烦啊~

  • Leafletjs 是完全免费的,重点是完全免费,功能上面可能有些不足但是人家免费啊,而且插件比较多,还有缺点就是差不多都是英文的,查文档比较难。

2. 结合项目点、线、区域的效果

  • 这里的点、线、区域都是提前绘制,把相应的坐标点存入数据库,最后在这个页面统一获取显示;

  • 这里的需求是,点==物资和人员线==安全路线区域==监测的范围,所有点、线、区域都要绑定地图与绑定报警事件,一旦事件触发,则显示相应的点、线、区域。

效果.gif
效果图.png

3. 布置地图

所有的操作都是建立在地图上的

// 最主要的是这一步,下面请求操作是根据业务需求添加
var maplet = L.map('map', {
            crs: L.CRS.Simple,
            minZoom: -2,
            zoomControl: false
        });

 var bounds = [
            [0, 0],
            [1021.5, 1023]
        ];
        var imageObj = new Image();
        var image = L.imageOverlay("", bounds).addTo(maplet);

// 请求数据,拿到地图的 URL,这里的地图数据在地图管理模块添加完成
mymap(mapid)
function mymap(mapid) {
            $.ajax({
                url: localStorage.baseUrl + `/Map/GetMapByMapId?TOKEN=${localStorage.token}&MAP_ID=${mapid}`,
                async: true,
                type: 'GET',
                dataType: "json",
                success: function (data) {
                    console.log(data)
                    var url = localStorage.temp + data.rows[0].URL;
                    imageObj.src = url;
                    init(url)
                }
            })

        }

// 布置地图
        function init(url) {
            imageObj.onload = function () {
                x = imageObj.width;
                y = imageObj.height;
                image.setUrl(imageObj.src).setBounds([[0, 0], [y, x]])
                console.log(x, y)
                maplet.setView([y / 2, x / 2], 0);
            }
        }

4. 点操作(自定义Marker

严格来说整个控件是没有绘制点的操作的,可以绘制圆,但是这里并不是圆,用绘制Marker点来显示

  • 首先定义一个图标(icon)对象
// 最后是根据坐标点来用图标显示,图标的属性可以自定义
var CustomerIcon = L.Icon.extend({
            options: {
             // 图标图片的地址
                iconUrl: '../../images/new/xiaofangdiliweizhi.svg',
              // 图标阴影的地址
                shadowUrl: '../../images/new/xiaofangdiliweizhi.svg',
              // 图标大小
                iconSize: [38, 95],
              // 图标偏离的位置
                shadowSize: [50, 64],
              // 图标阴影的大小
                iconAnchor: [20, 65]
            }
        });
  • 通过点击事件创建Marker,获取点坐标
// 创建地图时的 maplet ,添加点击事件
maplet.on('click', (ev) => {
            console.log(ev)
            // 创建 marker
            let marker = new L.Marker(ev.latlng, {
                // 图标
                icon: new CustomerIcon()
            }).addTo(maplet)

            // 打印点的横纵坐标
            console.log(ev.latlng.lat,ev.latlng.lng)
            // 根据需求,横纵坐标点 push 进数组
            var mark = []
            mark.push(ev.latlng.lat)
            mark.push(ev.latlng.lng)
            // 保存到数据库的函数
            layop(mark)
        })
  • 效果


    点坐标.gif

5. 绘制线

绘制线与绘制点的本质相同,最终的目的都是获取点坐标数组

  • 绘制线例子
// 动态绘线主要涉及到三个事件:click,dbclick,mousemove。
// click确定线的折点,dbclick确定线的终点,mousemove绘制鼠标移动过程中图形的变化。

var points=[]
    var lines=new L.polyline(points)
    var tempLines=new L.polyline([])
    map.on('click', onClick);    //点击地图
    map.on('dblclick',onDoubleClick);


    //map.off(....) 关闭该事件

    function onClick(e)
    {

        points.push([e.latlng.lat,e.latlng.lng])
        lines.addLatLng(e.latlng)
        map.addLayer(lines)
        map.addLayer(L.circle(e.latlng,{color:'#ff0000',fillColor:'ff0000',fillOpacity:1}))
        map.on('mousemove',onMove)//双击地图

    }
    function onMove(e) {
        if(points.length>0) {
            ls=[points[points.length-1],[e.latlng.lat,e.latlng.lng]]
            tempLines.setLatLngs(ls)
            map.addLayer(tempLines)
        }
    }

    function onDoubleClick(e)
    {
        L.polyline(points).addTo(map)
        points=[]
        lines=new L.polyline(points)
        map.off('mousemove')
    }
  • 结合项目添加事件
//绘制线路---start--
// 点击事件,点击后可以绘制
        $("#overlayCompany").on("click", function () {
            mapopen = true;
        })

var linesline = new L.polyline([])
var tempLines = new L.polyline([], {
            dashArray: 10
        })

maplet.on('click', onClick); //点击地图
maplet.on('dblclick', onDoubleClick);
maplet.on('mousemove', onMove);//双击地图

function onClick(e) {
            if (mapopen) {
                pointsline.push([e.latlng.lat, e.latlng.lng])
                linesline.addLatLng(e.latlng)
                maplet.addLayer(linesline)
                maplet.addLayer(L.circle(e.latlng, {
                    color: '#ff0000', fillColor: 'ff0000', fillOpacity: 1
                }))
                maplet.on('mousemove', onMove)
            }
        }

function onMove(e) {
            if (mapopen) {
                if (pointsline.length > 0) {
                    lsline = [pointsline[pointsline.length - 1], [e.latlng.lat, e.latlng.lng]]
                    tempLines.setLatLngs(lsline)
                    maplet.addLayer(tempLines)
                }
            }
        }

// 鼠标双击事件(双击绘制线结束)
function onDoubleClick(e) {
            if (mapopen) {
                var polygon = L.polyline(pointsline).addTo(maplet)
                ploverlays.push({polygon})
                overlays = pointsline.slice(0, pointsline.length - 1);
                // 坐标点数组,主要的就是获取这个坐标点数组,下面的操作根据需求进行
                pointsline = []

                linesline.remove()
                tempLines.setLatLngs([]);
                linesline = new L.polyline(pointsline)
                mapopen = false;

                // 根据需求处理坐标点形式
                var polygon2 = "";
                overlays.forEach(function (item, index) {
                    polygon2 += item[0] + "-" + item[1] + ",";
                })
                polygon2 = polygon2.split(",");
                var polygonnew = polygon2.slice(0, polygon2.length - 1).join(",")
                console.log(polygonnew)

                    // 添加函数等需求
                    optiontype = "add";
                    $("#subregion").text("提交");
                    initmodal()
                    $("#editregion").modal({
                        backdrop: 'static',
                        keyboard: false
                    });
                  $("#mapid").val(''+mapfloor+'');
                  $("#region").val(''+polygonnew+'');
            }
        }
  • 效果


    绘制线.gif

    线坐标.png

6. 绘制面(多边形)

绘制面与绘制线本质也是相同的,主要也是获得坐标点

  • 绘制多边形的例子
    var points=[]
    var lines=new L.polyline([])
    var tempLines=new L.polyline([],{dashArray:5})
    
    map.on('click', onClick);    //点击地图
    map.on('dblclick',onDoubleClick);
    map.on('mousemove',onMove)//双击地图

    //map.off(....) 关闭该事件

    function onClick(e)
    {
        points.push([e.latlng.lat,e.latlng.lng])
        lines.addLatLng(e.latlng)
        map.addLayer(tempLines)
        map.addLayer(lines)
        map.addLayer(L.circle(e.latlng,{color:'#ff0000',fillColor:'ff0000',fillOpacity:1}))

    }
    function onMove(e) {
        if(points.length>0) {
            ls=[points[points.length-1],[e.latlng.lat,e.latlng.lng],points[0]]
            tempLines.setLatLngs(ls)
            // map.addLayer(tempLines)
        }
    }

    function onDoubleClick(e)
    {
        L.polygon(points).addTo(map)
        points=[]
        //map.removeLayer(tempLines)
        //tempLines.remove()
        lines.remove()
        tempLines.remove()
        lines=new L.polyline([])
    }
  • 效果


    区域效果展示.gif

7. 总结

上面的绘制操作是得到坐标点存入数据库,而最终需要取用坐标点来展示

  • 获得点展示
// 上面异步获取数据 pointdata ,里面包含坐标点信息
for (let i = 0; i < pointdata.length; i++) {
                        // 坐标点
                        let matpoint = pointdata[i].POSITION ? pointdata[i].POSITION.split(",") : [];
                        console.log(matpoint)

                        let maticon = pointdata[i].ICON

                        // 图标
                        var myicon = '' + maticon + ''
                        var iconmat = new L.Icon({
                            iconUrl: '../../images/new/' + myicon + '.svg',
                            shadowUrl: '../../images/new/' + myicon + '.svg',
                            iconSize: [25, 41],
                            iconAnchor: [12, 41],
                            popupAnchor: [1, -34],
                            shadowSize: [41, 41]
                        })

                        var markermat = null;
                        markermat = L.marker(matpoint, {
                            icon: iconmat
                        });
                        // 显示名字
                        markermat.bindTooltip(pointdata[i].ITEM_NAME ? pointdata[i].ITEM_NAME : pointdata[i].LABEL_ID).openTooltip();
                        // 显示弹窗
                        var popupmat = L.popup({
                            maxWidth: 700,
                            maxHeight: 600
                        }).setLatLng(matpoint)
                        
                        buildings.addLayer(markermat);
                    }
                    buildings.addTo(maplet)
  • 获得线展示

流动线效果(动态线渲染),需要添加插件 leaflet-ant-path.js

// 异步获取到相应数据后,执行函数 line()
function line(longLatList) {
            if (path) {
                maplet.removeLayer(path);
            }
           // 流动线效果(动态线渲染),需要添加插件 ‘leaflet-ant-path.js’
            var antPath = L.polyline.antPath;
            var path = antPath(longLatList, {
                "paused": false,     //暂停  初始化状态
                "reverse": false,  //方向反转
                "delay": 150,    //延迟,数值越大效果越缓慢
                "dashArray": [20, 35], //间隔样式
                "weight": 10,   //线宽
                "opacity": 0.5,  //透明度
                "color": "red", //颜色
                "pulseColor": "#FFFFFF"  //块颜色
            });
            path.addTo(maplet).bindPopup("green to red");
            // 缩放地图到折线所在区域
            maplet.fitBounds(path.getBounds());
        }
  • 获得多边形展示

polArr 为点的数组,可以是多维数组,以 [ [[a1 ], [ a2]], [[b1 ], [ b2]],...... ] 形式都可以

// polArr 为点的数组,可以是多维数组,以 [ [[a1 ], [ a2]], [[b1 ], [ b2]],...... ] 形式都可以
function getRegion(polArr) {
            // console.log(polArr)
            var polygon = L.polygon(polArr, {
                color: '#000eff',
                fillColor: '#0000ed',
                weight: 0.2
            }).addTo(maplet);
        }

上述是结合个人的项目来整理的,官网的例子要清楚很多!

点个赞呗!

你可能感兴趣的:(Leafletjs--点、线、多边形的绘制)