Обновите файл Geojson с помощью геолокации [Onclick]

У меня есть локальный файл .json с координатами широты и долготы для каждой функции, а также пустой столбец Расстояние (случайное число 999).

Общая цель состоит в том, чтобы отобразить маркеры на карте листовки и отфильтровать ее на основе геопокрытия с помощью кнопки.

Я пытаюсь создать одну кнопку, которая может:

  1. Получить мое текущее местоположение

  2. Рассчитать расстояние для каждой функции в моем файле json (для цикла)

  3. [Точка блокировки] Обновите столбец "Расстояние" или создайте новый столбец

  4. отфильтровать файл json на основе расстояния (например, показать мне маркеры, где расстояние меньше 100 км)

Меня вдохновил этот пример, но я столкнулся с проблемой "адского обратного вызова". Я сейчас на 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)
};

Есть ли у вас какие-либо рекомендации о том, как структурировать мой код для доступа к данным с обновленным столбцом «Расстояние»?

Спасибо


person HazimoRa3d    schedule 16.07.2019    source источник
comment
console.log(data.features[0].properties.distance); вызывается перед data.features[i].properties.distance = ....   -  person Roland Starke    schedule 16.07.2019
comment
Хорошая точка! Я нашел решение благодаря вашему замечанию   -  person HazimoRa3d    schedule 16.07.2019


Ответы (1)


У меня есть решение!

Мне нужно было только поставить var Distance100 сразу после цикла For

С помощью этих функций: При нажатии кнопки вы можете фильтровать маркеры на карте Leaflet на основе вашего текущего местоположения (путем обновления расстояния в файле json)

Здесь рассматриваются многие случаи: чтение/доступ и обновление локального файла Geojson, фильтрация маркеров листовки по щелчку, использование координат геолокации в другой функции, вычисление расстояния...

обновленный код приведен ниже (загрузка карты и элементов управления не распространяется):

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

Скриншот моей карты

введите здесь описание изображения

Надеюсь, это может помочь другим в их случаях использования

Не стесняйтесь оптимизировать код и поделитесь им с нами.

person HazimoRa3d    schedule 16.07.2019