zoukankan      html  css  js  c++  java
  • Leafletjs--点、线、多边形的绘制

    Leafletjs 学习

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

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

    0. 其它

    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);
            }
    

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

    点个赞呗!

  • 相关阅读:
    python 写入txt的新方法
    python 对excel进行截图
    python 关于excel弹窗——请注意,您的文档的部分内容可能包含了文档检查器无法删除的个人信息解决方法
    python win32com 读取带密码的excel
    移动硬盘——显示盘符但打不开
    python datetime和time的一些疑惑解答 及 获取上年同期、上月等日期
    pyinstaller 打包exe程序读不到配置文件No such file
    Python之——爱心代码参与情人节
    《易学设计模式》-笔记
    "高级"数据库小结
  • 原文地址:https://www.cnblogs.com/jry199506/p/11370069.html
Copyright © 2011-2022 走看看