Leaflet separated div element interaction

隐身守侯 提交于 2019-12-23 23:18:51

问题


I am struggling for a bit now with this interaction and finding the right solution on that matter is a quite difficult task (for now).

So, I have created map with some basic points using GeoJSON format (created with PHP & MySQL.). And I'm wondering, is it possible to show rednered points in seperated div element, outside map?

Example:

My question is this? Is it possible when I click on list from right side to automatically open that same clicked element on map? (as shown on picture above)?

Here is code that I'm using to generate map and GeoJSON but that only generates points on map panel.

var karta = L.tileLayer.wms("http://geoportal.dgu.hr/wms?", {
        layers: 'DOF', // možemo još dodati slojeve za 'TK25', 'DOF', 'HOK'
        attribution: "http://geoportal.dgu.hr/ "
});

rasvjeta_kvar_hum = new L.geoJson(null, {
  pointToLayer: function (feature, latlng) {
  return L.marker(latlng, {
    icon: L.icon({
        iconUrl: "img/poweroutage_1.png",
        iconSize: [20, 28],
        iconAnchor: [12, 28],
        popupAnchor: [0, -25]
      })
  });
},
onEachFeature: function (feature, layer) {
if (feature.properties) {
  var content = "<table class='table table-striped table-bordered table-condensed'>" + "<tr><th>Šifra trafostanice</th><td>" + feature.properties.ts_sifra + 
      "</td></tr>" + "<tr><th>Naziv trafostanice</th><td>" + feature.properties.ts_naziv + "</td></tr>" +  
      "<tr><th>Kod lampe</th><td>" + feature.properties.sifra_lampe + "</td></tr>" +
      "<tr><th>Tip/snaga lampe</th><td>" + feature.properties.tip_lampe + "</td></tr>" +
      "<tr><th>Vrsta stupa</th><td>" + feature.properties.vrsta_stupa + "</td></tr>" +
      "<tr><th>Naziv naselja</th><td>" + feature.properties.naziv_naselja + "</td></tr>" +
      "<tr><th>Adresa</th><td>" + feature.properties.adresa + "</td></tr>" 
      "</table>";
layer.bindPopup(content);}}
});

$.getJSON("php/rasvjeta_kvar.php", function (data) {
    rasvjeta_kvar_hum.addData(data);
  });


var map = L.map('map', {
    center: [46.205481, 15.666011],
    zoom: 14,
    layers: [karta, rasvjeta_kvar_hum]
  });

var baseLayers = {
    "Podloga": karta
  };

  var overlays = {
    "Rasvjetna tijela": rasvjeta_kvar_hum
  };

  L.control.layers(baseLayers, overlays,{
    collapsed: false
  }).addTo(map);

I've be trying to resolve my issue following this answer but for now without any luck.

Some guidance or pointers would be highly appreciative, thank you.

UPDATE

Let's say that I'm one step closer (but still pretty far) for completing my task.

Using code below I've have successfully created elements in right panel but with some limitations.

// Create or retrieve the data
var DOF = L.tileLayer.wms(" http://geoportal.dgu.hr/wms?", {
    layers: 'DOF'
});

let people = [
    {
      name: 'FIRST POINT',
      latLng: [46.210888, 15.647540],
      id: '2342fc7'
    },
    {
      name: 'SECOND POINT',
      latLng: [46.211888, 15.647540],
      id: 'djf3892'
    },
    {
      name: 'THIRD POINT',
      latLng: [46.2120888, 15.647540],
      id: '2837hf3'
    }
];

// Create the group
let group = L.layerGroup(),
    list = document.getElementById('list')

// Create the map
var map = L.map('map',{
        center:[46.15796, 15.75336],
        zoom:13,
        layers: DOF
        });


// Loop through the data
people.forEach(person => {
  let marker = L.marker(person.latLng, {
    icon: L.icon({
        iconUrl: "img/power_green.png",
        iconSize: [20, 28],
        iconAnchor: [12, 28],
        popupAnchor: [0, -25]
      }),
        title: person.name,
        riseOnHover: true
      });

  // Add each marker to the group
  group.addLayer( marker );

  // Save the ID of the marker with it's data
  person.marker_id = group.getLayerId(marker);
})

// Add the group to the map
group.addTo(map);

// Click handler for handling
function onClick(data) {
  let { marker_id } = data,
      marker = group.getLayer(marker_id);

  map.panTo( marker.getLatLng() );
}

// Append list items
people.forEach(person => {
  let item = document.createElement('ul');

  item.innerHTML = `<a href="#" class="list-group-item">${person.name}<br><b>CODE: </b>${person.id}</a>`;
  item.addEventListener('click', onClick.bind(null, person));

  list.appendChild(item);
});

I'm wondering is it possible to loop trough php generated GeoJSON using this block of code

var lampe_hum_150n = L.geoJson(null, {
  pointToLayer: function (feature, latlng) {
    return L.marker(latlng, {
      icon: L.icon({
        iconUrl: "img/power_red.png",
        iconSize: [20, 28],
        iconAnchor: [12, 28],
        popupAnchor: [0, -25]
      }),
      title: feature.properties.sifra_lampe,
      riseOnHover: false,
      riseOffset: 100
    });
  },
  onEachFeature: function (feature, layer) {
    if (feature.properties) {

      var content = "<table class='table table-striped table-bordered table-condensed'>" + "<tr><th>Šifra trafostanice</th><td>" + feature.properties.ts_sifra + 
      "</td></tr>" + "<tr><th>Naziv trafostanice</th><td>" + feature.properties.ts_naziv + "</td></tr>" +  
      "<tr><th>Kod lampe</th><td>" + feature.properties.sifra_lampe + "</td></tr>" +
      "<tr><th>Tip/snaga lampe</th><td>" + feature.properties.tip_lampe + "</td></tr>" +
      "<tr><th>Vrsta stupa</th><td>" + feature.properties.vrsta_stupa + "</td></tr>" +
      "<tr><th>Adresa</th><td>" + feature.properties.adresa + "</td></tr>" +
      "<tr"+ (feature.properties.datum === 'Nema servisa' ? ' class="danger"' : '' || feature.properties.datum != 'Nema servisa' ? ' class="success"' : '') +"><th>Zadnji servis</th><td>" + feature.properties.datum + "</td></tr>" 
      "</table>";

      layer.on({
        click: function (e) {
          $("#feature-title").html(feature.properties.ts_sifra +'-'+ feature.properties.sifra_lampe+'<br>TS - '+feature.properties.ts_naziv);
          $("#feature-info").html(content);
          $("#featureModal").modal("show");
          highlight.clearLayers().addLayer(L.marker([feature.geometry.coordinates[1], feature.geometry.coordinates[0]], {icon:ikonaClick_A}));
        }
      });
      $("#feature-list tbody").append('<tr class="feature-row" id="' + L.stamp(layer) + '" lat="' + layer.getLatLng().lat + '" lng="'
      + layer.getLatLng().lng + '"><td style="vertical-align: middle;"><img width="16" height="18" src="img/power_red.png"></td><td class="feature-name">'
      + layer.feature.properties.sifra_lampe + '</td><td style="vertical-align: middle;"><i class="fa fa-chevron-right pull-right"></i></td></tr>');
      rasvjetaSloj_150n.push({
        // pretražuje nam na topbaru po lokaciji
        // ako zamijenimo lokaciju i operator
        // onda će nam pretraživati po operatoru, a ne po lokaciji
        ts: layer.feature.properties.ts_sifra + '-',
        name: layer.feature.properties.sifra_lampe,
        tip: layer.feature.properties.tip_lampe,
        address: layer.feature.properties.adresa,
        source: "Lampe",
        id: L.stamp(layer),
        lat: layer.feature.geometry.coordinates[1],
        lng: layer.feature.geometry.coordinates[0]
      });
    }
  }
});
$.getJSON("php/rasvjeta_150n.php", function (data) {
  lampe_hum_150n.addData(data);
  map.addLayer(rasvjeta_sloj_150n);
});

instead of this:

let people = [
    {
      name: 'FIRST POINT',
      latLng: [46.210888, 15.647540],
      id: '2342fc7'
    },
    {
      name: 'SECOND POINT',
      latLng: [46.211888, 15.647540],
      id: 'djf3892'
    },
    {
      name: 'THIRD POINT',
      latLng: [46.2120888, 15.647540],
      id: '2837hf3'
    }
];

When I try to loop trough GeoJSON using this code

let people = $.getJSON("php/rasvjeta_150n.php", function (data) {
});

instead block from above, I get this error message

Uncaught TypeError: people.forEach is not a function

And here it is PHP code for generating GeoJSON from MySQL:

UPDATE II

With help of fellow ghybs I've manage to create some interaction between external items and map markers. But as I click on elements from external list it only zooms me on the same marker.I would like (if possible) when I click item on external list to zoom me on that same marker on the map.

Picture:

If I click on list with the code H12 it zooms me on the map marker with different code on the map.

Here is the code:

function goTo(layer) {
    map.panTo(layer.getLatLng());
    layer.openPopup();
}

$.getJSON("php/rasvjeta_kvar.php", function(data) {
    geojson = L.geoJson(data, {
        pointToLayer: function(feature, latlng) {
            return L.marker(latlng, {
                icon: L.icon({
                    iconUrl: "img/power_red.png",
                    iconSize: [20, 28],
                    iconAnchor: [12, 28],
                    popupAnchor: [0, -25]
                }),
                title: feature.properties.sifra_lampe,
                riseOnHover: false,
                riseOffset: 100
            });
        },
        onEachFeature: function(feature, layer) {
            layer.bindPopup(feature.properties.tip_lampe +
                "<br>" + feature.properties.adresa + " u m<sup>2</sup>");

            $("#list").append('<a href="#" class="list-group-item">' + layer.feature.properties.sifra_lampe + ' - ' + layer.feature.properties.ts_sifra + '</a>');

            list.addEventListener("click", function() {
                goTo(layer);
            });
        }
    });
    geojson.addTo(map);
});

回答1:


What you describe is a common use case. I am pretty sure there should be plenty resources (in particular on SO) that provide the same functionality.

As for the TypeError you report, note that jQuery's $.getJSON returns a jqXHR object, not an array.

As to implement your functionality, you already know that you can perform instructions for each GeoJSON feature through the onEachFeature option of L.geoJSON constructor. Therefore, why not simply building your list items in there, instead of trying to parse your people array separately? This is actually what your code seems to do, by appending a new row into #feature-list table.

The biggest advantage of this approach is that you can directly link your external item "click" event listener to the appropriate layer / marker, since it is available as parameter of the onEachFeature function:

function goTo(layer) {
    map.panTo(layer.getLatLng());
    layer.openPopup();
}

L.geoJSON(null, {
    onEachFeature: function (feature, layer) {
        // Whatever you want to add to your layer.

        // Build your external item.
        // Then attach the "click" event listener.
        item.addEventListener("click", function () {
            goTo(layer);
        });
    }
});



回答2:


One way of doing this is to bind a new popup to the same position on the map...

function openPopup(elementRightSide){
   L.popup() 
            .setLatLng(elementRightSide.lat, elementRightSide.lng])
            .setContent(elementRightSide.content)
            .openOn(map);
}


来源:https://stackoverflow.com/questions/41694291/leaflet-separated-div-element-interaction

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!