3

I'm trying to create a button inside a popup which will draw a line on the map when clicked. Line coordinates must be based on the properties of the point layer.

I saw some ansewrs on stack and it should look like this http://jsfiddle.net/cfsg6t7u/ but the coords are hardocded and it should be based on the point layer data.

In my code buttons make no action. Here is my HTML file with js:

<!DOCTYPE html>
    <html>
        <head>
            <title>test</title>
            <meta charset="UTF-8">
    
            <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"/>
            <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
            <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    
            <script type="text/javascript" src="./points.js"></script>
    
            <style>
                html, body {
                    height: 100%;
                    margin: 0;
                }
                #map {
                    width: 100%;
                    height: 100%;
                }
            </style>
        </head>
    
        <body>
            <div id='map'></div>
    
            <script>
                var map = L.map('map').setView([0, 0], 5)
                var OSM = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
    
                var pointsLayer = L.geoJSON(points, {
                    pointToLayer: function (feature, latlng) {
                        var content = feature.properties.name;
                        content += "<br><button id='draw" + feature.properties.name + "'>draw a line</btn>";
                        
                        $("#draw" + feature.properties.name).click(function() {
                        var line = L.polyline([[latlng.lat, 0], [latlng.lng, 360]])
                        });
    
                        return L.marker(latlng).bindPopup(content);
                }})
                
                pointsLayer.addTo(map);
            </script>
        </body>
    </html>

Here is another version of adding clickable button but it gives an html object:

var pointsLayer = L.geoJSON(points, {
            pointToLayer: function (feature, latlng) {

                return L.marker(latlng).bindPopup(feature.properties.name + '<br>' +
                 $("<button id='draw" + feature.properties.name + "'>draw a line</button>").click(function() {
                var line = L.polyline([[latlng.lat, 0], [latlng.lng, 360]]);
                })[0]);
        }})

Here is sample points.js data:

    var points = {
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
                                                                                                                                  
"features": [
{ "type": "Feature", "properties": { "name": "pierwszy"}, "geometry": { "type": "Point", "coordinates": [ 0, 0 ] } },
{ "type": "Feature", "properties": { "name": "drugi"}, "geometry": { "type": "Point", "coordinates": [ 0, 5 ] } },
]}

I know Leaflet and JS as little as it works enough to aim my goal.

EDIT:

Because this question got a lot of views here is my final map with buttons I wanted to create. Maybe it will be helpful to see the result for people who want to achieve similar effect. https://marylagis.github.io/webmaps/citiesonlines/

4
  • If I understand you correctly, you want to draw line between the two points in GeoJSON?
    – TomazicM
    Dec 11, 2022 at 18:22
  • See stackoverflow.com/questions/73963988/… Dec 11, 2022 at 20:53
  • @TomazicM I want to draw a line between a point in geojson and a point created on the fly partially based on this point coords in geojson. I couldn't figure out how to make click function working properly. Bernd Loigge answered me below. Thanks for your interest.
    – Maryla
    Dec 12, 2022 at 21:27
  • If his answer helped you solve your problem, it's customary on GIS SE site to accept it, to let other people know that problem was resolved.
    – TomazicM
    Dec 12, 2022 at 21:29

1 Answer 1

8

No need to use jQuery here IMHO. You can pass an HTMLElement to the bindPopup function. So just create a div and the button as javascript objects and construct the container that way. Then you can add an onclick function to the button where you can access the latlng or the whole feature.

Working JsFiddle.

const points = {
  "type": "FeatureCollection",
  "crs": {
    "type": "name",
    "properties": {
      "name": "urn:ogc:def:crs:OGC:1.3:CRS84"
    }
  },

  "features": [{
      "type": "Feature",
      "properties": {
        "name": "pierwszy"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [0, 0]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "name": "drugi"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [0, 5]
      }
    },
  ]
}
const map = L.map('map').setView([0, 0], 5);
const osm = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);

const pointsLayer = L.geoJSON(points, {
  pointToLayer: (feature, latlng) => {
    const div = document.createElement("div");
    div.innerHTML = `<br>${feature.properties.name}<br>`;

    const button = document.createElement("button");
    button.innerHTML = "Create Line";

    button.onclick = function() {
      const line = L.polyline([latlng, [10, 5]]);
      line.addTo(map);
    }

    div.appendChild(button);

    return L.marker(latlng).bindPopup(div);
  }
});

pointsLayer.addTo(map);
1
  • Thanks! I just saw jQuery in others answers on stack so tried to use it as well. In another attempt I tried to create div, then button and combine it together but still button wasn't working and I was focused on using jQuery thinking it will be easier.
    – Maryla
    Dec 12, 2022 at 21:13

Your Answer

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

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