添加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的值导致拖动无效果
    
posted @ 2021-04-21 12:50  lisicn  阅读(469)  评论(0编辑  收藏  举报