使用地理定位 [Onclick] 更新 Geojson 文件

Update Geojson file using Geolocation [Onclick]

我有一个本地 .json 文件,每个要素的坐标为 lat/long,还有一个空列 Distance(随机输入 999)。

总体目标是在传单地图中显示标记并使用按钮根据 geolcoation 对其进行过滤。

我正在尝试创建一个按钮,它能够:

  1. 获取我的当前位置

  2. 计算我的 json 文件中每个特征的距离(for 循环)

  3. [阻塞点]更新列距离/或创建新列

  4. 根据距离过滤 json 文件(例如,显示距离小于 100 公里的标记)

我从中得到灵感example 但是遇到了 "callback hell" 问题。 我现在正处于第 3 步:我设法计算了距离。但不能在函数外工作。

这是我正在使用的代码,阻塞在 For 循环中:距离列未更新

var allmarkers = L.markerClusterGroup();
var markersdist100 = L.markerClusterGroup();

// Load json file
var promise = $.getJSON("./data/FILE.geojson");
promise.then(function(data) {
    // Update distance in json data
    // Geolocation part to get current position
    var userPositionPromise = new Promise(function(resolve, reject) {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(function(data1) {
                resolve(data1);
            }, function(error) {
                reject(error);
            });
        } else {
            reject({
                error: 'browser doesn\'t support geolocation'
            });
        };
    });
    userPositionPromise.then(function(dataa) {
        lat = dataa.coords.latitude;
        lng = dataa.coords.longitude;
        console.log(lng); // check ok : lng of current location
        console.log(data.features.length); //check ok : json length for iteration
        // For loop to calculate the new distance
        for (var i = 0; i < data.features.length; i++) {
            data.features[i].properties.distance = getDistanceFromLatLonInKm(lat, lng, data.features[i].geometry.coordinates[0], data.features[i].geometry.coordinates[1]);
            console.log(data.features[i].properties.distance); //check ok : showing the right distance
        }
    })
    console.log(data.features[0].properties.distance); //check BUG : showing initial distance [999]

    //all data
    var all = L.geoJson(data, {
        pointToLayer: style_markers,
    });

    // data filtered by distance, see the function [filter_distance]
    var distance100 = L.geoJson(data, {
        pointToLayer: style_markers,
        filter: filter_distance
    });

    // Filter distance on button click
    $("#distance100").click(function() {
        markersdist100.addLayer(distance100);
        allmarkers.addLayer(all);

        map.addLayer(markersdist100);
        map.removeLayer(allmarkers);
    });

});

// FUNCTIONS

function filter_distance(feature, other) {
    return feature.properties.distance < 100;
};

function getDistanceFromLatLonInKm(lat1, lon1, lat2, lon2) {
    var R = 6371; // Radius of the earth in km
    var dLat = deg2rad(lat2 - lat1); // deg2rad below
    var dLon = deg2rad(lon2 - lon1);
    var a =
        Math.sin(dLat / 2) * Math.sin(dLat / 2) +
        Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
        Math.sin(dLon / 2) * Math.sin(dLon / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = R * c; // Distance in km
    return d;
};

function deg2rad(deg) {
    return deg * (Math.PI / 180)
};

关于如何构建我的代码以使用更新的距离列访问数据,您有什么建议吗

谢谢

我找到了解决方案!

我只需要将 var distance100 放在 For 循环之后

使用这些功能:单击按钮,您可以根据当前位置过滤传单地图中的标记(通过更新 json 文件中的距离)

这里解决了很多情况:read/access 并更新 Geojson 本地文件,点击过滤 Leaflet 标记,在另一个函数中使用地理定位坐标,计算距离 ...

更新后的代码如下(加载地图和控件未涵盖):

var allmarkers = L.markerClusterGroup(); //markercluster plugin using leaflet
var markersdist100 = L.markerClusterGroup();

// Load json file
var promise = $.getJSON("./data/FILE.geojson");
promise.then(function(data) {
    // Update distance in json data
    // Geolocation part to get current position
    var userPositionPromise = new Promise(function(resolve, reject) {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(function(data1) {
                resolve(data1);
            }, function(error) {
                reject(error);
            });
        } else {
            reject({
                error: 'browser doesn\'t support geolocation'
            });
        };
    });
    userPositionPromise.then(function(dataa) {
        lat = dataa.coords.latitude;
        lng = dataa.coords.longitude;
        console.log(lng); // check ok : lng of current location
        console.log(data.features.length); //check ok : json length for iteration
        // For loop to calculate the new distance
        for (var i = 0; i < data.features.length; i++) {
            data.features[i].properties.distance = getDistanceFromLatLonInKm(lat, lng, data.features[i].geometry.coordinates[0], data.features[i].geometry.coordinates[1]);
            console.log(data.features[i].properties.distance); //check ok : showing the right distance
        };

        // data filtered by distance, see the function [filter_distance]
        var distance100 = L.geoJson(data, {
            pointToLayer: style_markers,
            filter: filter_distance
        });

        // Filter distance on button click
        $("#distance100").click(function() {
            markersdist100.addLayer(distance100);
            allmarkers.addLayer(all);

            map.addLayer(markersdist100);
            map.removeLayer(allmarkers);
        });

    });

    //all data
    var all = L.geoJson(data, {
        pointToLayer: style_markers,
    });

});

// FUNCTIONS

function filter_distance(feature, other) {
    return feature.properties.distance < 100;
};

function getDistanceFromLatLonInKm(lat1, lon1, lat2, lon2) {
    var R = 6371; // Radius of the earth in km
    var dLat = deg2rad(lat2 - lat1); // deg2rad below
    var dLon = deg2rad(lon2 - lon1);
    var a =
        Math.sin(dLat / 2) * Math.sin(dLat / 2) +
        Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
        Math.sin(dLon / 2) * Math.sin(dLon / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = R * c; // Distance in km
    return d;
};

function deg2rad(deg) {
    return deg * (Math.PI / 180)
};

我的地图截图

希望这可以帮助其他人在他们的用例中

欢迎优化代码分享给我们