1

I built a photo map with Leaflet which contains geotagged photos. I managed to fetch the timestamp and coordinates of the pictures with a php script and now I want to filter the images by it's recording date. The JSON Data of the imported images contain information about year, month and day.

This is my Leaflet setup:

var photoLayer = L.photo.cluster({ spiderfyDistanceMultiplier: 1.2 }).on('click', function (evt) {
                evt.layer.bindPopup(L.Util.template('<span class="DatumPopup">Aufnahmedatum: {DateTimeOriginal} <span class="Uhrzeit">{Time}</span><img src="{url}" height="auto" width="100%"/>', evt.layer.photo), {
                    className: 'leaflet-popup-photo',
                    minWidth: 400
                }).openPopup();
            });

            //Call the next function as soon as the page loads
            window.onload = callForImages()

            //Makes a request, loading the getimages.php file
            function callForImages() {

                //Create the request object
                var httpReq = (window.XMLHttpRequest)?new XMLHttpRequest():new ActiveXObject("Microsoft.XMLHTTP");

                //When it loads,
                httpReq.onload = function() {

                    //Convert the result back into JSON
                    var result = JSON.parse(httpReq.responseText);

                    //Load the images
                    loadImages(result);
                }

                //Request the page
                try {
                    httpReq.open("GET", "getphotos.php", true);
                    httpReq.send(null);
                } catch(e) {
                    console.log(e);
                }
            }


            //Generates the images and sticks them into the photolayer
            function loadImages(images) {
                var photos = [];
                //Loop over the images
                for(var i = 0; i < images.length; i++) {
                    photos.push({
                        lat: images[i].lat,
                        lng: images[i].lng,
                        url: images[i].filename,
                        DateTimeOriginal: images[i].DateTimeOriginal,
                        Year: images[i].Year,
                        YearMonth: images[i].YearMonth,
                        Time: images[i].Time,

                        //If you have thumbnails, switch the comments on the following lines.
                        thumbnail: images[i].filename
                        //thumbnail: images[i].thumbnail
                    });
                }
                photoLayer.add(photos).addTo(map);
                //Add the photos to the map
                map.fitBounds(photoLayer.getBounds());
                //Zoom the map to the photos
            }

}).addTo( map );

How can I apply a filter(filter by day f.e.) to the json data in the loadimages function? I'd like to filter by button click or do a range slider(But I think this one is quite compliacted).

2
  • Where/when you want to apply filter? I suppose not in the loadImages function, since this could easily be done. Some UI selection after all is loaded? Please edit your question with additional details.
    – TomazicM
    Nov 1, 2022 at 19:32
  • I think applying it in the loadImages function would be the best idea performance wise. Still, I am not quite sure how to start here. The filter then should be bound to a graphical element like a button or a slider. Nov 2, 2022 at 8:09

1 Answer 1

1

On possible way to dynamically filter displayed photos would be to first load all photos in some global array photos and then when needed, first clean photoLayer and then add desired/filtered photos based on some global min/max values startDate and endDate into photoLayer.

Code could then look something like this:

var photoLayer = L.photo.cluster({
  spiderfyDistanceMultiplier: 1.2
});
photoLayer.on('click', function (evt) {
  evt.layer.bindPopup(L.Util.template('<span class="DatumPopup">Aufnahmedatum: {DateTimeOriginal} <span class="Uhrzeit">{Time}</span><img src="{url}" height="auto" width="100%"/>', evt.layer.photo), {
    className: 'leaflet-popup-photo',
    minWidth: 400
  }).openPopup();
});

var photos = [];
var startDate = null;
var endDate = null;

function getAllImages(images) {
  for (var i = 0; i < images.length; i++) {
    photos.push({
      lat: images[i].lat,
      lng: images[i].lng,
      url: images[i].filename,
      DateTimeOriginal: images[i].DateTimeOriginal,
      Year: images[i].Year,
      YearMonth: images[i].YearMonth,
      Time: images[i].Time,
      thumbnail: images[i].filename
    });
  }
}

function loadFilteredImages() {
  var filteredPhotos = [];
  for (var i = 0; i < photos.length; i++) {
    if (startDate && (photos[i].DateTimeOriginal < startDate))
    || (endDate && (photos[i].DateTimeOriginal > endDate)) continue;
    filteredPhotos.push(photos[i]);
  }
  photoLayer.clearLayers();
  if (filteredPhotos.length > 0) {
    photoLayer.add(filteredPhotos);
    if (!map.hasLayer(photoLayer) photoLayer.addTo(map);
    map.fitBounds(photoLayer.getBounds());
  }
}

function callForImages() {
  var httpReq = (window.XMLHttpRequest)?new XMLHttpRequest():new ActiveXObject("Microsoft.XMLHTTP");
  httpReq.onload = function() {
    var result = JSON.parse(httpReq.responseText);
    getAllImages(result);
    loadFilteredImages();
  }
  try {
    httpReq.open("GET", "getphotos.php", true);
    httpReq.send(null);
  } catch(e) {
    console.log(e);
  }
}

window.onload = callForImages();

This way when needed you can just change startDate and endDate values and call loadFilteredImages() function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.