问题
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