Hello
I try to implement a leaflet pluging, for display a local hosted shapefile. The display of the shapefile work, but i want to add a layer control (for togle shapefile layer).
the plugin link : https://github.com/calvinmetcalf/shapefile-js
the demo link :http://leaflet.calvinmetcalf.com/#3/32.69/10.55
I want to implement the layer control on demo page
<script>
var m = L.map('map').setView([0, 0 ], 10);
var watercolor =
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: 'Map tiles by <a href="http://stamen.com">Stamen
Design</a>, <a href="http://creativecommons.org/licenses/by/3.0">CC BY
3.0</a> — Map data © OpenStreetMap contributors, CC-BY-SA'
}).addTo(m);
var shpfile = new L.Shapefile('Fr_adm.zip', {
onEachFeature: function(feature, layer) {
if (feature.properties) {
layer.bindPopup(Object.keys(feature.properties).map(function(k) {
return k + ": " + feature.properties[k];
}).join("<br />"), {
maxHeight: 200
});
}
}
});
shpfile.addTo(m);
shpfile.once("data:loaded", function() {
console.log("finished loaded shapefile");
});
// initialize stylable leaflet control widget
var control = L.control.UniForm(null, overlayMaps, {
collapsed: false,
position: 'topright'
}
);
// add control widget to map and html dom.
control.addTo(m);
</script>
The shapefile Fr_adm.zip is displayed, but no layer control.
Thank for your help.
Your problem is that overlayMaps is not defined. Open your console and you should see an error stating this.
Looking at the documentation for L.control.UniForm maps (an extension of leaflet), we can see:
/ **
* standard leaflet code.
** /
// initialize stylable leaflet control widget
var control = L.control.UniForm(null, overlayMaps, {
collapsed: false,
position: 'topright'
}
);
What is overlayMaps in this? To answer we need to take a look at the documentation for standard leaflet code. overlayMaps is a list of key, object pairs:
... we’ll create two objects. One will contain our base layers and
one will contain our overlays. These are just simple objects with
key/value pairs. The key sets the text for the layer in the control
(e.g. “Streets”), while the corresponding value is a reference to the
layer (e.g. streets).
var baseMaps = {
"Grayscale": grayscale,
"Streets": streets
};
var overlayMaps = {
"Cities": cities
};
Consequently, overlayMaps in your example should look like:
var overlayMaps = {"Name To Display":shpfile }
Once defined you should be able to create your layer control as normal.
i see a mistake in the code, no overlayer value. So i try with this :
<script type="text/javascript" charset="UTF-8">
//----------------
var watercolor = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
});
var geo = L.geoJson({features:[]},{onEachFeature:function popUp(f,l){
var out = [];
if (f.properties){
for(var key in f.properties){
out.push(key+": "+f.properties[key]);
}
l.bindPopup(out.join("<br />"));
}
}});
var m = L.map('map', {
center: [10, -1],
zoom: 6,
layers: [watercolor, geo ]
});
//}}).addTo(m);
var base = 'Fr_admin.zip';
shp(base).then(function(data){
geo.addData(data);
});
var baseMaps = {
"BaseLayer": watercolor
};
var overlays = {
"shapefile": geo
};
L.control.layers(baseMaps,overlays).addTo(m);
</script>
It 's work, i can chose to display the shapefile or not.
But dont return all segmentation like here :http://leaflet.calvinmetcalf.com/#3/32.69/10.55
thank you
I am new to Leaflet and I was wondering how to load markers from a database into a leaflet map in php.
I have a php code that gets the latitude and logitude from the database depending on the ward selected and encodes it in json,
On the main page I have 3 links namely ward1,ward2,ward3, onclicking the link the different markers wrt that particular ward are loaded on the map accordingly.
How do I call these markers from the json file for each of the wards instead of manually writing it?
<section>
<div id="gmap1"></div>
<ul>
<li><a id="ward1" href="#">ward1</a></li>
<li><a id="ward2" href="#">ward2</a></li>
<li><a id="ward3" href="#">ward3</a></li>
</ul>
<script>
var lat = 17.9487;
var lng = 73.8919;
var zoom = 10;
var map = new L.Map('gmap1');
var osmUrl='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
var osmAttrib='Map data © OpenStreetMap contributors';
var osm = new L.TileLayer(osmUrl, {minZoom: 5, maxZoom: 18, attribution: osmAttrib});
map.addLayer(osm);
map.setView(new L.LatLng(lat, lng), zoom);
// add markers
var aa = L.marker(["17.9507900000","73.8886383300"]).bindPopup('AA'),
bb = L.marker([17.9497333300,73.8975800000]).bindPopup('BB'),
cc = L.marker(["17.9507616700","73.8972833300"]).bindPopup('CC'),
dd = L.marker(["17.9468733300","73.8952383300"]).bindPopup('DD'),
ee = L.marker([17.9509700000,73.8885616700]).bindPopup('EE'),
ff = L.marker([17.9503500000,73.8949550000]).bindPopup('FF')
var ward1 = L.layerGroup([aa, bb]);
var ward2 = L.layerGroup([cc, dd]);
var ward3 = L.layerGroup([ee,ff]);
$("#ward1").click(function(event) {
event.preventDefault();
if(map.hasLayer(ward1)) {
$(this).removeClass('selected');
map.removeLayer(ward1);
} else {
map.addLayer(ward1);
$(this).addClass('selected');
}
});
$("#ward2").click(function(event) {
event.preventDefault();
if(map.hasLayer(ward2)) {
$(this).removeClass('selected');
map.removeLayer(ward2);
} else {
map.addLayer(ward2);
$(this).addClass('selected');
}
});
$("#ward3").click(function(event) {
event.preventDefault();
if(map.hasLayer(ward3)) {
$(this).removeClass('selected');
map.removeLayer(ward3);
} else {
map.addLayer(ward3);
$(this).addClass('selected');
}
});
</script>
</section>
Have you tried searching on SO? How do you add marker to map using leaflet map.on('click', function) event handler - the same can be applied to when your loading it from a JSON request.
I want the Google map show marker with JSON feeds. but it's not working. I can't find the actual problem. so here is my code:
var map;
// The JSON data
var json = [{
"OpperationErrorMsg":"",
"IsSuccess":true,
"ResultId":1000,
"Timestamp":"2016-10-12T18:00:07.0232702Z",
"Echo":null,
"InSandbox":true,
"DebugMessages":[
],
"MissingDetails":[
],
"ResponseData":[
{
"CallTimeLocal":"2016-10-10T06:28:48.7330000",
"IncidentId":3374,
"IncidentNumber":"HC2016004034",
"CallTime":"2016-10-10T10:28:48.7330000",
"ElapsedSeconds":0,
"Location":"2712 E HANNA AVE",
"BuildingName":null,
"BuildingNumber":null,
"NatureId":6743,
"FirePriorityId":1,
"CoordinateX":-82.429500000000,
"CoordinateY":28.003389000000
},
{
"CallTimeLocal":"2016-10-10T11:28:36.7000000",
"IncidentId":3382,
"IncidentNumber":"HC2016004042",
"CallTime":"2016-10-10T15:28:36.7000000",
"ElapsedSeconds":0,
"Location":"1220 APOLLO BEACH BLVD S",
"BuildingName":"Apollo Beach Marina",
"BuildingNumber":null,
"NatureId":8035,
"FirePriorityId":1,
"CoordinateX":-82.422369000000,
"CoordinateY":27.781254000000
},
{
"CallTimeLocal":"2016-10-10T14:29:59.8830000",
"IncidentId":3387,
"IncidentNumber":"HC2016004047",
"CallTime":"2016-10-10T18:29:59.8830000",
"ElapsedSeconds":0,
"Location":"9600 SHELDONWOOD RD",
"BuildingName":null,
"BuildingNumber":null,
"NatureId":6420,
"FirePriorityId":12,
"CoordinateX":-82.580530000000,
"CoordinateY":28.034779000000
},
{
"CallTimeLocal":"2016-10-10T15:27:37.7270000",
"IncidentId":3389,
"IncidentNumber":"HC2016004049",
"CallTime":"2016-10-10T19:27:37.7270000",
"ElapsedSeconds":0,
"Location":"4691 GALLAGHER RD",
"BuildingName":"Strawberry Crest High School",
"BuildingNumber":null,
"NatureId":7873,
"FirePriorityId":2,
"CoordinateX":-82.236450000000,
"CoordinateY":28.021233000000
}
],
"CurrentStatusData":null
}];
function initialize() {
// Giving the map som options
var mapOptions = {
zoom: 6,
center: new google.maps.LatLng(25.0,-80.0)
};
// Creating the map
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
// Looping through all the entries from the JSON data
for(var i = 0; i < json.length; i++) {
// Current object
var obj = json[i];
// Adding a new marker for the object
var marker = new google.maps.Marker({
position: new google.maps.LatLng(obj.CoordinateY,obj.CoordinateX),
map: map,
draggable: true,
animation: google.maps.Animation.DROP,
title: obj.BuildingName // this works, giving the marker a title with the correct title
});
// Adding a new info window for the object
var clicker = addClicker(marker, obj.title);
} // end loop
// Adding a new click event listener for the object
function addClicker(marker, content) {
google.maps.event.addListener(marker, 'click', function() {
if (infowindow) {infowindow.close();}
infowindow = new google.maps.InfoWindow({content: content});
infowindow.open(map, marker);
});
}
}
// Initialize the map
google.maps.event.addDomListener(window, 'load', initialize);
html, body, #map-canvas {
height: 100%;
margin: 0;
padding: 0;
}
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=true"></script>
<script src="https:////cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<div id="map-canvas"></div>
I will be using it on a HTML page. Though the JSON data will be updated automatically so i can't change the JSON Arrays.
Thanks!
I found these problems in your code:
In your loop where you create each marker, you are looping over the json array. However, this is not your array of marker data. json[0] is your main object, and json[0].ResponseData is the marker array that you need to loop over. So I put that value in a variable named responses and looped over that instead. I don't know if the JSON data could have more than one object in its outermost array; if it does you would need an outer loop to handle those. For now I assumed there is just one outer object addressed with json[0].
When you call addClicker you pass in obj.title which doesn't exist. Presumably you meant obj.BuildingName.
Your click handler references a variable called infowindow, but on the first click that variable does not exist and causes an error. So I declared infowindow as a global window.
So, how did I find these problems? Using the JavaScript debugger. Normally I would add a debugger; statement at the beginning of the initialize() function and single step through the code to see what is going on. This would reveal that where the main loop sets var obj = json[i]; it isn't getting the expected value.
That works great on a normal web page, but it doesn't seem to work well in the embedded snippet here on SO. (The debugger shows the wrong source line.) So instead I started adding console.log(); statements where it looked like things might be going wrong, such as console.log( 'obj:', obj ); immediately after the var obj = assignment.
Also, it's nice to automatically zoom and center the map according to where the markers are located. I added a bit of code using a LatLngBounds which is extended for each marker, and then a map.fitBounds() after all the markers are created. If you do that you don't need to explicitly zoom and center the map when first creating it, so I removed those. (Otherwise the map is displayed at one position and then repositioned.)
One caveat with the fitBounds(): if there were no markers, then the map wouldn't get displayed at all. To handle that case you would want to check for the case where responses.length is zero and call map.setZoom() and map.setCenter() with default values.
I marked the changed lines with //// to make them easy to find:
var map, infowindow; ////
// The JSON data
var json = [{
"OpperationErrorMsg":"",
"IsSuccess":true,
"ResultId":1000,
"Timestamp":"2016-10-12T18:00:07.0232702Z",
"Echo":null,
"InSandbox":true,
"DebugMessages":[
],
"MissingDetails":[
],
"ResponseData":[
{
"CallTimeLocal":"2016-10-10T06:28:48.7330000",
"IncidentId":3374,
"IncidentNumber":"HC2016004034",
"CallTime":"2016-10-10T10:28:48.7330000",
"ElapsedSeconds":0,
"Location":"2712 E HANNA AVE",
"BuildingName":null,
"BuildingNumber":null,
"NatureId":6743,
"FirePriorityId":1,
"CoordinateX":-82.429500000000,
"CoordinateY":28.003389000000
},
{
"CallTimeLocal":"2016-10-10T11:28:36.7000000",
"IncidentId":3382,
"IncidentNumber":"HC2016004042",
"CallTime":"2016-10-10T15:28:36.7000000",
"ElapsedSeconds":0,
"Location":"1220 APOLLO BEACH BLVD S",
"BuildingName":"Apollo Beach Marina",
"BuildingNumber":null,
"NatureId":8035,
"FirePriorityId":1,
"CoordinateX":-82.422369000000,
"CoordinateY":27.781254000000
},
{
"CallTimeLocal":"2016-10-10T14:29:59.8830000",
"IncidentId":3387,
"IncidentNumber":"HC2016004047",
"CallTime":"2016-10-10T18:29:59.8830000",
"ElapsedSeconds":0,
"Location":"9600 SHELDONWOOD RD",
"BuildingName":null,
"BuildingNumber":null,
"NatureId":6420,
"FirePriorityId":12,
"CoordinateX":-82.580530000000,
"CoordinateY":28.034779000000
},
{
"CallTimeLocal":"2016-10-10T15:27:37.7270000",
"IncidentId":3389,
"IncidentNumber":"HC2016004049",
"CallTime":"2016-10-10T19:27:37.7270000",
"ElapsedSeconds":0,
"Location":"4691 GALLAGHER RD",
"BuildingName":"Strawberry Crest High School",
"BuildingNumber":null,
"NatureId":7873,
"FirePriorityId":2,
"CoordinateX":-82.236450000000,
"CoordinateY":28.021233000000
}
],
"CurrentStatusData":null
}];
function initialize() {
// Giving the map som options
var mapOptions = {
////
};
// Creating the map
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var bounds = new google.maps.LatLngBounds(); ////
// Looping through all the entries from the JSON data
var responses = json[0].ResponseData; ////
for(var i = 0; i < responses.length; i++) { ////
// Current object
var obj = responses[i]; ////
// Adding a new marker for the object
var position =
new google.maps.LatLng( obj.CoordinateY, obj.CoordinateX ); ////
bounds.extend( position ); ////
var marker = new google.maps.Marker({
position: position, ////
map: map,
draggable: true,
animation: google.maps.Animation.DROP,
title: obj.BuildingName
});
// Adding a new info window for the object
var clicker = addClicker(marker, obj.BuildingName); ////
} // end loop
map.fitBounds( bounds ); ////
// Adding a new click event listener for the object
function addClicker(marker, content) {
google.maps.event.addListener(marker, 'click', function() {
if (infowindow) {infowindow.close();}
infowindow = new google.maps.InfoWindow({content: content});
infowindow.open(map, marker);
});
}
}
// Initialize the map
google.maps.event.addDomListener(window, 'load', initialize);
html, body, #map-canvas {
height: 100%;
margin: 0;
padding: 0;
}
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=true"></script>
<script src="https:////cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<div id="map-canvas"></div>
I want to update the value of two hidden fields on my form based on marker position. I read this link to get my answer, and this is my final code
<script>
var map = L.map('map', {
center: [33.505, 53.9],
zoom: 5
});
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
map.on('dblclick', addMarker);
var Marker;
function addMarker(e) {
//remove previous markers
if (Marker) {
map.removeLayer(Marker);
UpdateLatLng(e);
}
// Add marker to map at click location; add popup window
Marker = new L.marker(e.latlng, {
draggable: true
}).addTo(map);
}
function UpdateLatLng(e) {
var latValue, lngValue;
latValue = e.latlng.lat;
lngValue = e.latlng.lng;
document.getElementById("map_lat").value = latValue;
document.getElementById("map_lng").value = lngValue;
//$("#map_lat").val() = latValue;
}
function UpdateLatLng2(e) {
var latValue, lngValue;
var position = marker.getLatLng();
latValue = position.lat;
lngValue = position.lng;
document.getElementById("map_lat").value = latValue;
document.getElementById("map_lng").value = lngValue;
//$("#map_lat").val() = latValue;
}
Marker.on('dragend', UpdateLatLng2);
</script>
The result is that my form fields are not updated on the first double click event, but they get updated on the next double clicks or after marker's dragend event instead. Why?
And why would the following code does not work while getElementById does?
$("#map_lat").val() = latValue;
Any help would be appreciated.
My form fields are not updated on the first double click, but get updated on the next double clicks. The form fields don't get updated after marker dragend; why?
This is how the first time your script runs,
map.on('dblclick', addMarker); //|You attach the double click event handler.
var Marker; //|You instansiate an undefined variable.
function addMarker(e) {
if (Marker) { //|On the first double click, Marker is undefined. Your code will not get into this if condition.
map.removeLayer(Marker);
UpdateLatLng(e); // But your function is here.
}
// Add marker to map at click location; add popup window
Marker = new L.marker(e.latlng, {
draggable: true
}).addTo(map);
}
On the first double click, UpdateLatLng(e) will never get called because your Marker is undefined. And the second double click, it will then get called.
You can update your addMarker function like,
function addMarker(e) {
//remove previous markers
if (Marker) {
map.removeLayer(Marker);
}
// Add marker to map at click location; add popup window
Marker = new L.marker(e.latlng, {
draggable: true
}).addTo(map);
UpdateLatLng(e);
}
But that's the worst way to update the marker position. I'd suggest that your code is a bit more like,
<script>
var map = L.map('map', {
center: [33.505, 53.9],
zoom: 5
});
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
map.on('dblclick', addOrUpdateMarkerPosition);
var Marker;
function addOrUpdateMarkerPosition(e) {
if (!Marker) {
// Marker is undefined, create a new marker..
// Add marker to map at click location; add popup window
Marker = new L.marker(e.latlng, {
draggable: true
}).addTo(map);
// Bind the event handlers
Marker.addListener('dragend', UpdateLatLng2);
}
else {
// Marker already exists, just update the position
Marker.setPosition(e.latlng);
}
}
function UpdateLatLng(e) {
var latValue, lngValue;
latValue = e.latlng.lat;
lngValue = e.latlng.lng;
document.getElementById("map_lat").value = latValue;
document.getElementById("map_lng").value = lngValue;
}
function UpdateLatLng2(e) {
var latValue, lngValue;
var position = marker.getLatLng();
latValue = position.lat;
lngValue = position.lng;
document.getElementById("map_lat").value = latValue;
document.getElementById("map_lng").value = lngValue;
}
</script>
BTW, do you know why this code is not working but getElementById works?
$("#map_lat").val() = latValue;
This code is using javascript external library which is jQuery. While getElementById is pure JS and does not need any library. To use it, you have basically just have to include the following script in your page.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I am using Leaflet to visualize map. Everything worked fine, until I added a checkbox to switch the data for the map.
I wrote it like this for the view:
<input type="checkbox" name="switch" class="switch-checkbox"onclick="change();" checked>
For the function in js :
function change()
{
var map = L.map('map').setView([37.8, -96], 4);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
if (document.querySelector('.onoffswitch-checkbox').checked) {
data = statesData;
L.geoJson(statesData).addTo(map);
} else {
L.geoJson(statesDataTwo).addTo(map);
}
Then I got an error that the map is already initialized. I tried to add map.remove(); before adding the new map. Like suggested here. But map is undefined. What is the way to do that? Thanks
Why are you adding new map? You probably have it already in global variable map, which is initialized on load. Work with this and change only layers on change/click. Something like this:
var map = L.map('map').setView([37.8, -96], 4);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18
}).addTo(map);
var geojsonLayers = {
'states': L.geoJson(statesData),
'statesTwo': L.geoJson(statesDataTwo)
};
function change()
{
if (document.querySelector('.onoffswitch-checkbox').checked) {
map.addLayer(geojsonLayers.states);
if (map.hasLayer(geojsonLayers.statesTwo)) {
map.removeLayer(geojsonLayers.statesTwo);
}
} else {
map.addLayer(geojsonLayers.statesTwo);
if (map.hasLayer(geojsonLayers.states)) {
map.removeLayer(geojsonLayers.states);
}
}
}