zoukankan      html  css  js  c++  java
  • 添加marker并绘制连接线

    什么是Marker:标记点

    什么是连接线:路径线

    最终效果:

    要求:

    1. marker为自定义的图形,并显示标记序号。
    2. 标记点可拖动,拖动期间不影响其连接线(跟随绘制)。
    3. 每两个点之间绘制连接线,样式为虚线。

    实现过程:

    1. 基于leafletjs,网址:https://leafletjs.com/
    2. 知晓如何增加marker。并增加至图层组(方便管理)。
    3. 如何增加连接线,并重新定义其样式。需要给marker绑定拖动事件。

    难点:

    1. 添加自定义marker
    2. 拖动时绘制连接线

    具体代码:

    //添加标记、移动标记、添加线
    //此处未粘贴mymap,参考官方文档创建一个map
    
    var marker_group = L.layerGroup([]) //存放marker
    marker_group.addTo(mymap) 
    
    var line_group = L.layerGroup([])  //为marker计数,不可放置同一组
    line_group.addTo(mymap)
    
    var polylinelist = []  //存放marker的坐标,用于生成连接线
    var polylinelist_cache = []  //存放marker的坐标,缓存坐标。因marker移动时,会产生两个坐标:新坐标、旧坐标,旧坐标在拖动期间是不变的,拖动的同时又要绘制连接线,需要一个中间变量来索引到发生变化的值。拖动事件停止后再将这两个值进行同步,即可开始下一次拖动。
    
    var lines = L.polyline([], {color: '#25db71', weight: 1, dashArray: [5, 5],})
    	//定义连接线的样式,dashArray表示虚线,[实线长度,实线间距]
    
    
    mymap.on("dblclick", function (e) {
        //双击事件,双击添加marker
        addMarker(e.latlng.lat, e.latlng.lng)
    })
    
    function redrawLine() {
        //给polyline设定新的坐标数据后,重新绘制
        lines.setLatLngs(polylinelist)
        lines.redraw()
    }
    
    
    function IniDivIcon(marker_id) {
        //初始化marker,使其具有编号,采用自定义icon对象
        return L.divIcon({
            className: 'my-div-icon',
            html: "<p class='text-center' style='margin-bottom:0;font-size:22px;color:#00ff3a;'>" +
            marker_id +
            "</p>" +
            "<img src='{% static 'http_app/index/img/position.png' %}' height=30 width=22>",
            iconSize: [22, 30],  //marker的宽,高
            iconAnchor: [11, 63], // 坐标值对应的marker位置。以marker左上角为[0,0],也就是你想标记的位置实际是marker的左上角,需要调整marker的底部尖端为实际标记位置
        });
    }
    
    function addMarker(lat, long) {
        //增加新的marker
        const marker_id = Object.keys(marker_group._layers).length + 1  //根据图层组内marker数量为marker添加编号
        const marker = L.marker([lat, long], {
            icon: IniDivIcon(marker_id),
            draggable: true,   //可拖动
        })
        
        marker_group.addLayer(marker)    //添加至图层组
        //为每个marker绑定事件。drag移动中不断触发更新连接线,dragend停止移动后触发polylinelist与polylinelist_cache同步
        marker.on("drag", function (e) {
            IconOnMove([e.latlng.lat, e.latlng.lng], [e.oldLatLng.lat, e.oldLatLng.lng])
        })
        marker.on("dragend", function (e) {
            polylinelist_cache = Array.from(polylinelist)   //坑1:polylinelist_cache = polylinelist会将内存地址引用,即深copy
        })
    
        //根据marker增加轨迹线
        const latlngs_length = polylinelist.push([lat, long])    //轨迹线数组
        polylinelist_cache.push([lat, long])                     //轨迹线缓存数组
        
        //如果只有1个 不添加连接线,2个添加连接线并将线添加至图层组,3个及以上则更新轨迹线数组
        if (latlngs_length >= 3) {                               
            redrawLine()
        } else if (latlngs_length < 3 && latlngs_length > 1) {
            lines.setLatLngs(polylinelist)
            line_group.addLayer(lines)
        }
    }
    
    function checkArray(src, value) {
        //校验两个数组是否一致
        if (src.length !== value.length) {
            return false;
        }
        for (var i = 0, l = src.length; i < l; i++) {
            // Check if we have nested arrays
            if (src[i] instanceof Array && value[i] instanceof Array) {
                // recurse into the nested arrays
                if (!src[i].equals(value[i]))
                    return false;
            } else if (src[i] !== value[i]) {
                // Warning - two different object instances will never be equal: {x:20} != {x:20}
                return false;
            }
        }
        return true;
    }
    
    function IconOnMove(new_latlng, old_latlng) {
        //移动marker,更新轨迹线
        if (polylinelist_cache.length < 2) {
            return
        }
        polylinelist_cache.forEach(function (value, index) {
            // 遍历连接线的数据列表,与 old_latlng对比,根据index赋予新值
            // const result = checkArray(value, old_latlng)   和下行可对换
            const result = value.toString() === old_latlng.toString()
    
            if (result) {
                polylinelist[index] = new_latlng
                redrawLine()
            }
        })
    }
    
    function clearAllIcon() {
        //清空所有图层组
        marker_group.clearLayers()
        line_group.clearLayers()
        polylinelist = []
        polylinelist_cache = []
    }
    

    踩坑:

    • 经典赋值问题:

      marker.on("dragend", function (e) {
          polylinelist_cache = Array.from(polylinelist)   //坑1:polylinelist_cache = polylinelist会将内存地址引用,即深copy
      })
      
      //此处原本内容为
          polylinelist_cache = polylinelist
      //即: `=`会将内存地址作为引用,即在第一次拖动停止后,再次拖动将会直接改变polylinelist_cache的值导致拖动无效果
      
  • 相关阅读:
    移动硬盘无法识别提示需要格式化的解决办法
    Cassandra 入门(资料收集)
    [转] NoSQL生态系统
    软件项目实施问题收集(LastUpdatedOn:20141117)
    Sql server 收缩日志
    关于重构需要了解的一些原则
    C#定时任务采用线程和队列实现
    [转]我是如何带领团队开发项目的
    ASP.NET MVC 多套皮肤解决方案
    Mysql 问题汇总(不断更新中...)
  • 原文地址:https://www.cnblogs.com/lisicn/p/14684735.html
Copyright © 2011-2022 走看看