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

上述是結合個人的項目來整理的,官網的例子要清楚很多!

點個贊唄!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM