单张屏幕距离到LatLng距离

时间:2020-09-13 00:30:09

标签: javascript leaflet

我想根据缩放级别组合标记。我没有使用Markercluster,而是使用自己的算法来检测应该组合哪些标记。该算法工作得很好。我唯一需要添加的是标记组合时基于缩放的条件。当前,距离在0.001之内的所有标记都将合并。我想要的是将屏幕上0.5厘米以内的每个标记合并在一起。因此,我需要一个将cm,px或其他距离转换为度数的函数。

一个例子:在18级缩放比例上,两个经度为0.00005的标记在我的屏幕上的距离接近0.3cm。

编辑: 这就是我所做的:

function in_range(location1, location2, map) {
    return get_distance_in_px(location1, location2, map) < 25;
}

function get_distance_in_px(location1, location2, map) {
    var p1 = map.latLngToContainerPoint(L.latLng(location1[0], location1[1]));
    var p2 = map.latLngToContainerPoint(L.latLng(location2[0], location2[1]));

    var a = p1.x - p2.x;
    var b = p1.y - p2.y;

    return Math.sqrt(a * a + b * b);
}

2 个答案:

答案 0 :(得分:1)

您可以获取latlng的containerPoint,然后计算距离:


map.on('zoomend',(e)=>{
    console.log(e);
    recalcZoom();
});

var DISTANCE = 20; //px
function recalcZoom() {
    var layers = findLayers(map);
    var resultLayers = []; //sturcture: {main: layer, childs: [];
    layers.forEach((layer)=>{
        if(resultLayers.length === 0){ // set the first layer as main layer
            resultLayers.push({
                main: layer,
                childs: []
            });
        }else{
            var found = false;
            var mainObj = null;
            var lastDis = null;
            resultLayers.forEach((rLayer)=>{
                var main = rLayer.main;
                var p1 = map.latLngToContainerPoint(main.getLatLng());
                var p2 = map.latLngToContainerPoint(layer.getLatLng());
                var dis = p1.distanceTo(p2);
                if(dis <= DISTANCE){ // distance between main layer and current marker is lower then DISTANCE
                    if(lastDis == null || dis < lastDis) { // a main layer is found, where the distance between them is lower
                        if(mainObj && mainObj.childs.indexOf(layer) > -1){ // remove the layer from the old main layer childs array
                            mainObj.splice(mainObj.childs.indexOf(layer),1);
                        }

                        rLayer.childs.push(layer);
                        found = true;
                        mainObj = rLayer;
                    }
                }
            });
            if(!found){ // if no main layer is found, add it as new main layer
                resultLayers.push({
                    main: layer,
                    childs: []
                });
            }
        }
    });

    console.log(resultLayers);
    // Logic to find center of all childs + main
    // remove the old layers and add the new clustered layer
    // keep in mind, that you have to store somewhere the original markers, else you can't recalc the clusters
}

function findLayers(map) {
// your logic to get the original layers
    let layers = [];
    map.eachLayer(layer => {
        if (layer instanceof L.Marker) {
            layers.push(layer);
        }
    });
    return layers;
}

您必须自己实施逻辑以找到所有子级+主层的中心,然后删除旧层并添加新的群集层。 但是请记住,您必须将原始标记存储在某个地方,否则无法重新计算聚类。

小例子:https://jsfiddle.net/falkedesign/ny9s17cb/(查看控制台)

答案 1 :(得分:0)

传单示例中的注释

使用圆柱形投影的缺点之一是 比例尺不是恒定的,并且测量距离或尺寸也不是 可靠,尤其是在低缩放级别时。

从技术上讲,Leaflet使用的圆柱投影是 保形的(保留形状),但不等距的(不保留) 距离),而不是相等的区域(不保留区域,因为 赤道附近的区域看起来比它们要小)。 learn more

话虽这么说,您实际上正在陷入很多难题,试图将尺寸准确地确定为一开始并不是可靠的测量。