0

I am working on a leaflet map which will allow a user to click on an area on the map and download respective river data based on the area of the click, however am struggling on the download functionality. I have included my current code and an image of the output of the code. How can I have the script download a file depending on which tile (see below image) the user clicks on? Ideally i'd like to use the download tag or have an on click JavaScript event so that each click of a tile downloads it's respective data.

<!DOCTYPE html>
<html>
<head>
    <title>GRWL test</title>
        <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css"
   integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ=="
   crossorigin=""/>
        <script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js"
   integrity="sha512-/Nsx9X4HebavoBvEBuyp3I7od5tA0UzAxs+j83KgC8PU0kgB4XiK4Lfe4y4cgBtaRJQEIFCW+oC506aPT2L1zw=="
   crossorigin=""></script>
        <style>
            #mapid {
                height: 1920px;
                width: 1080px;
            }
        </style>

        <script src="leaflet-src.js"></script>
        <script type="text/javascript" src="../dist/leaflet.ajax.js"></script>
        <script src="spin.js"></script>
        <script src="leaflet.spin.js"></script>

    </head>
    <body>
    <div id="mapid"></div>
      <script>

        var map = L.map('mapid').setView([0.478320099108, -79.381377894799996], 14);
            L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
                    attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>',
                    maxZoom: 18,
                    id: 'mapbox.streets',
                    accessToken: 'pk.eyJ1IjoiamltbXlzd2lzaGVyIiwiYSI6ImNqc29vYW02ejAxYjI0YW94NnBlcDhpYWEifQ.6DiOztwTzMJu3eBEyHHfrw'
            }).addTo(map);

        function popUp(f,l){
            var out = [];
            if (f.properties){
                for(key in f.properties){
                    out.push(key+": "+f.properties[key]);
                }
                l.bindPopup(out.join("<br />"));
                var anchor = document.createElement('a');
                anchor.href = "C:\leaflet\leaflet-ajax-gh-pages\example\NA17.geojson";
                anchor.target = '_blank';
                anchor.download = "NA17.geojson";
                anchor.click();
            }
        }
        var jsonTest = new L.GeoJSON.AJAX(["tiles.geojson"],{onEachFeature:popUp}).addTo(map);
</script>
    </body>
</html>

Output of the code, creates a grid system over the map:

kboul
  • 13,836
  • 5
  • 42
  • 53

2 Answers2

0

Why dont you try the on click function for the map. You can start from here and then find out what you clicked with the response of the click. For example you can check the lat lng and compare it to an array to see if you clicked on a some part of the map that had some downloadable item. From there its easy to download.

map.on('click', function(e) {
    alert(e.latlng);
    console.log(e);
    // download something
    /* if(something == something){
          e.preventDefault(); 
          window.location.href = 'downloadMe/riverData.doc';
       }
    */
} );
Icewine
  • 1,851
  • 1
  • 12
  • 22
0

It appears you are after Layer.click event which:

Fired when the user clicks (or taps) the layer.

Since leaflet-ajax plugin extends L.GeoJSON object you could consider to register click event for a layer:

function onEachFeature(feature, layer) {
    layer.on({
      click: downloadContent
    });
  }

where

new L.GeoJSON.AJAX(
  [
      "https://raw.githubusercontent.com/calvinmetcalf/leaflet-ajax/gh-pages/example/counties.geojson"
    ],
    { onEachFeature: onEachFeature }
).addTo(map);

Then, once the user clicks (or taps) the layer, the associated GeoJSON object could be downloaded like this:

function downloadContent(event) {
    var fileName = event.target.feature.properties.COUNTY + ".json";
    var featureJson = event.target.feature;
    downloadJson(featureJson, fileName);
}

Example

var map = L.map("map").setView([42.2, -71], 8);
var url =        "https://api.mapbox.com/styles/v1/mapbox/streets-v9/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1Ijoibml0dHlqZWUiLCJhIjoid1RmLXpycyJ9.NFk875-Fe6hoRCkGciG8yQ";
var options = {
        attribution:
          '© <a href="https://www.mapbox.com/map-feedback/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
};
L.tileLayer(url, options).addTo(map);

function downloadContent(event) {
        var fileName = event.target.feature.properties.COUNTY + '.json';
        var featureJson = event.target.feature;
        downloadJson(featureJson,fileName)
}

//from https://stackoverflow.com/a/30800715/1375553 
function downloadJson(json, fileName) {
        var data =
          "data:text/json;charset=utf-8," +
          encodeURIComponent(JSON.stringify(json));
        var link = document.createElement("a");
        link.setAttribute("href", data);
        link.setAttribute("download", fileName);
        document.body.appendChild(link); // required for firefox
        link.click();
        link.remove();
}

function onEachFeature(feature, layer) {
        layer.on({
          click: downloadContent
        });
      }
      new L.GeoJSON.AJAX(
        [
          "https://raw.githubusercontent.com/calvinmetcalf/leaflet-ajax/gh-pages/example/counties.geojson"
        ],
        { onEachFeature: onEachFeature }
).addTo(map);
#map {
   width: 960px;
   height: 550px;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css"/>
<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-ajax/2.1.0/leaflet.ajax.js"></script>
<div id="map"></div>
Vadim Gremyachev
  • 57,952
  • 20
  • 129
  • 193
  • Your answer is spot on, I just have one question. On click it will download the rectangular tile, how can I have it download river data that falls within the tile as opposed to the actual tile? I have a dataset of rivers that has a matching attribute to the tiles. I am thinking a conditional statement in the onEachFeature function, any thoughts? – M. C. Griffin Apr 20 '19 at 02:25
  • To identify dataset by matching attribute sounds like a good idea, I would store river properties in feature.properties, in that case dataset could be identified on layer click – Vadim Gremyachev Apr 20 '19 at 07:42
  • 1
    Could you elaborate on how I would store it in the feature.properties? I am a little lost to be honest. Thank you for your help @VadimGremyachev – M. C. Griffin Apr 20 '19 at 14:19
  • I was assuming river dataset (geojoson?) contains some metadata (feature.properties) that would allow to identify which file to download.. but might be mistaken without seeing some sample data – Vadim Gremyachev Apr 21 '19 at 06:24
  • the river dataset are shapefiles, because the file is too large and renders very slowly as a geojson I am instead loading the tile data as pictured in the original post since it loads quicker. However I would like to download the corresponding river data based on which tile is clicked. The river data and tile data have a matching attribute but don't know how tie each tile back to each shapefile. – M. C. Griffin Apr 21 '19 at 06:31
  • then maybe expose matching attr as part of shapefile, say `{river-id}.geojson`. On layer click the corresponding river id could be retrieved like this : `let riverId = feature.properties["river-id"]` – Vadim Gremyachev Apr 21 '19 at 07:46
  • 1
    Thank you for all your help Vadim! I will give this a try. – M. C. Griffin Apr 21 '19 at 07:52