I am developing a website that has a mapping and i am using leaflet. Now im on the part that i will hide /show markers that i made.
below is my code finding the image that i want and use it as a marker
var Icon1 = L.icon({
iconUrl: 'legends/fire.GIF',
iconSize: [170, 120], // size of the icon
iconAnchor: [100, 120], // point of the icon which will correspond to marker's location
popupAnchor: [-7, -80] // point from which the popup should open relative to the iconAnchor
the other one below is my code when putting the mark on the map.
function mark()
{
if (select1.value === "Fire"){
var note = document.getElementById('note');
var datepick = document.getElementById('demo1');
var timepick = document.getElementById('timepick');
map.on('click', function(e){
var marker = new L.Marker(e.latlng,{icon: Icon1});
marker.bindPopup("</a><br><strong>FIRE</strong></br><strong>Date:</strong>"+datepick.value+"</br><strong>Time:</strong>"+timepick.value+"</br><strong>Address:</strong>"+note.value+"<strong><br><strong>Suspect Sketch</strong><br><a href=legends/suspect.jpg rel=lightbox><img src = legends/suspect.jpg height=100 width = 100/>").addTo(map);
marker.on('dragend');
});
This is my code in hiding the marker.
script type="text/javascript">
function closure(marker){
var checkbox = document.getElementById("chbx")
$(chbx).click(function(){
if(map.hasLayer(marker)){
window.alert("I want to hide the marker");
}
window.alert("I want to show the marker");
})
}
</script>
This is just what i wanted.
1.Add A marker on the map
2.Hide/Show the marker in the map
3.Make this happen during run time or when i try it.
I try everything but still nothing happens.
What is the right thing to do to call my hide/show function in checkbox?
Here's a way to do it:
Define a function which takes marker as its argument, and with jQuery create a function to toggle the visibility of the layer:
function closure(marker){
$('#yourcheckbox id').click(function(){
if(map.hasLayer(marker)){
map.removeLayer(marker)
}
else {map.addLayer(marker)}
})
}
Than, inside the click event of the map, add the closure function:
map.on('click', function(e){
marker = new L.Marker(e.latlng).addTo(map);
closure (marker)
})
With .addTo(map) should works.
However, you can use addLayer and removeLayer for add/remove markers:
var marker = new L.Marker(e.latlng,{icon: Icon1});
marker.bindPopup('<div>Hello World</div>');
//add the marker to the map
map.addLayer(marker);
//remove the marker from the map
map.removeLayer(marker);
I assume that you have created the map
In some cases for hiding markers we may use such method, may be.
marker._icon.style.display = 'none';
if (value._popup._isOpen)
{
marker.closePopup();
}
For show markers after hiding.
marker._icon.style.display = '';
Related
I have a leaflet.js map with a collection of markers, which can be shown/hidden in a legend div done with plugin Leaflet.StyledLayerControl (I think this is not too relevant but just in case).
I can capture the event when layers are shown or hidden and in that event I would like to zoom to fit all visible markers.
There are a few questions in SO with a very similar title but most of them pretend to fit zoom to a known collection of markers, which is not my case (some other questions with very similar subject refer to Google maps, not leaflet).
So, the question would be:
A) Can I set zoom to fit all visible markers?
B) or, how can I get an array of all visible markers to apply the other solutions seen?
This is how I create markers on map:
const icon_general = L.divIcon({html: '<i class="fas fa-map-marker fa-2x"></i>', iconSize: [20, 20], className: 'node_icon'});
var node_10031 = L.marker([40.7174605,-3.9199218],{ icon: icon_general}).addTo(layer1);
node_10031.bindPopup('<h2>Title</h2>');
var node_10032 = L.marker([40.7184576,-3.9202692],{ icon: icon_general}).addTo(layer1);
node_10032.bindPopup('<h2>Title</h2>');
var node_10032 = L.marker([40.7361371,-3.9453966],{ icon: icon_general}).addTo(layer2);
node_10032.bindPopup('<h2>Title</h2>');
Layers are then hidden or shown and I can capture that event, that is where I want to modifiy zoom or loop through visible markers.
EDIT (final solution based on Seth Lutske response):
This is my final solution, maybe it's less eficient as on each click it loops through all visible markers in map, but after some attempts this was the succesful one (I wasn't able to manage properly the individual events for add/remove layer):
function setZoom2Visible()
{
var visibleLayerGroup = new L.FeatureGroup();
mymap.eachLayer(function(layer){
if (layer instanceof L.Marker)
visibleLayerGroup.addLayer(layer);
});
const bounds = visibleLayerGroup.getBounds();
mymap.fitBounds(bounds);
}
$('.menu-item-checkbox input[type=checkbox]').click(function(){
setZoom2Visible();
});
Create a featureGroup and add the markers to it:
const myGroup = L.featureGroup([node_10031, node_10032, node_10033]);
On whatever event you're using to capture the markers being added to the map, you can get the bounds of the featureGroup and set the map's bounds to that:
function onMarkersAddedEventHandler(){
const bounds = myGroup.getBounds();
map.fitBounds(bounds);
}
Now if you're saying that each marker has its own toggle in the UI, it's a bit more complicated. You'll have to attach an event to each marker's UI checkbox, and on change of that checkbox, add or remove the marker from the group, then reset the bounds:
const node_10031_checkbox = document.querySelector('input[type="checkbox"]#10031');
function onMarkersAddedEventHandler(e){
if (e.target.checked){
myGroup.addLayer(node_10031)
} else {
myGroup.removeLayer(node_10031)
}
const bounds = myGroup.getBounds();
map.fitBounds(bounds);
}
I am trying to create a function to be called by Button that drops a marker at the center of the mapView and allows it to be draggable until a button with id="doneMarkerbtn" has been clicked to disable dragging.
My following code was able to drop a marker at the center of the mapView. However, the marker is not draggable at all. Hope someone can look at my code and help me with this. Thanks.
Additional Info: This code is on a .js file which I import both at the <head> and <body> of my html. Import twice due to some other functions that requires it at different part of the html. Also note that this code is to be used for a Cordova/Phonegap app.
/* Draws marker on center of mapView and allow user to edit by dragging until done */
function drawMarker() {
//Extend the Default marker class
var PinMarker = L.Icon.Default.extend({
options: {
iconUrl: 'img/marker.png', //directory of pin image
iconSize: [26,40] //[width,height] of pin image in pixels
}
});
var pinMarker = new PinMarker();
var marker = L.marker(map.getCenter(), {icon: pinMarker, draggable: true}).addTo(map); //drop marker on center of mapView
marker.on('dragend', function (e) { //event activates at the end of a drag
var coords = e.target.getLatLng(); //gets new latlng of marker
var lat = coords.lat;
var lng = coords.lng;
var latlng = lat+","+lng;
marker.bindPopup(latlng).openPopup().update(); //popup showing dragend latlng
});
var stopDrawButton = document.getElementById('doneMarkerbtn'); //set #doneMarkerbtn as stopDrawButton
stopDrawButton.addEventListener('click', function(){ //when stopDrawButton clicked
marker.dragging.disable(); //disable dragging on marker
});
}
I have pins on my leaflet.js map where the image is determined by the status of the object they are representing. For example, online and offline users - online are green and offline are red. I do this by adding a class to the divIcon and then control the images with css.
I have now added marker clustering to my map. What I want to do is determine the color of the cluster by the majority of status' within the cluster. My first idea was to do something like this:
this.markers = L.markerClusterGroup({
iconCreateFunction: function(cluster) {
// Use this somehow to filter through and look at the pin elements
console.log(cluster.getAllChildMarkers());
return new L.DivIcon({ html: /* ?? */ });
}
});
But unfortunately I am not able to access the HTML elements from the array returned from getAllChildMarkers.
Anyone have any ideas on how I might be able to do this? Or a way to get the pin's HTML element?
Thanks
EDIT:
Here is where I create my map pins (assigned to my backbone model's mapPin attribute):
that.mapPins.org = L.divIcon({
className: 'org-div-icon',
html: "<div class='org-status "+ org.getGroupStatus() +"'></div>",
iconSize: [35, 35],
iconAnchor: [18, 17]
});
And here is how I change the class dynamically:
$(model.get('mapPin')._icon).find('.org-status').attr('class', 'org-status ' + model.getGroupStatus());
I thought that I would be able to access _icon from the return of getAllChildMarkers like I do above, but it doesn't seem to be there.
You can use getAllChildMarkers to get all of the markers in the cluster. Once you have a marker, you can access its class with marker.options.icon.options.className. You can access the html with marker.options.icon.options.html
Here's some code that uses underscore.js functions to count the number of markers with each class, find the one that's most popular, and use that class for the cluster marker.
var markers = L.markerClusterGroup({
iconCreateFunction: function (cluster) {
var childMarkers = cluster.getAllChildMarkers();
// count how many there are of each class
var counts = _.countBy(childMarkers, function(marker) {
// class at icon level
//return marker.options.icon.options.className;
// class inside html
return $(marker.options.icon.options.html).attr('class');
});
// get the class with the highest count
var maxClass = _.invert(counts)[_.max(counts)];
// use this class in the cluster marker
return L.divIcon({ html: cluster.getChildCount(), className: maxClass });
},
});
for a small project I am working on, I need to be able to place a marker on a leaflet.js powered image-map and update the position of this marker, if it gets dragged. I use the following code to try this, but it fails.
I get the error 'marker not defined'. I don't know why it's not working - maybe you guys could help me out? ;)
function onMapClick(e) {
gib_uni();
marker = new L.marker(e.latlng, {id:uni, icon:redIcon, draggable:'true'};
map.addLayer(marker);
};
marker.on('dragend', function(event){
var marker = event.target;
var position = marker.getLatLng();
alert(position);
marker.setLatLng([position],{id:uni,draggable:'true'}).bindPopup(position).update();
});
In the code snippet above, marker is not defined at the time the event handler is added. Try the following where the dragend listener is added immediately following the creation of the Marker:
function onMapClick(e) {
gib_uni();
marker = new L.marker(e.latlng, {id:uni, icon:redIcon, draggable:'true'});
marker.on('dragend', function(event){
var marker = event.target;
var position = marker.getLatLng();
console.log(position);
marker.setLatLng(position,{id:uni,draggable:'true'}).bindPopup(position).update();
});
map.addLayer(marker);
};
You were also missing a bracket at the end of your new L.Marker() line.
You also put position into an array in the call to setLatLng but it is already a LatLng object.
I'm using leaflet/JavaScript for the first time and I want to display a map, with a GeoJSON layer which change on every move… To only show points on the area.
This is my code source:
// Function to refresh points to display
function actualiseGeoJSON() {
// Default icon for my points
var defaultIcon = L.icon({
iconUrl: '../images/icones/cabane.png',
iconSize: [16, 16],
iconAnchor: [8, 8],
popupAnchor: [0, -8]
});
// We create each point with its style (from GeoJSON file)
function onEachFeature(feature, layer) {
var popupContent = '' + feature.properties.nom + "";
layer.bindPopup(popupContent);
var cabaneIcon = L.icon({
iconUrl: '../images/icones/' + feature.properties.type + '.png',
iconSize: [16, 16],
iconAnchor: [8, 8],
popupAnchor: [0, -8]
});
layer.setIcon(cabaneIcon);
}
// We download the GeoJSON file (by using ajax plugin)
var GeoJSONlayer = L.geoJson.ajax('../exportations/exportations.php?format=geojson&bbox=' + map.getBounds().toBBoxString() + '',{
onEachFeature: onEachFeature,
pointToLayer: function (feature, latlng) {
return L.marker(latlng, {icon: defaultIcon});
}
}).addTo(map);
}
// We create the map
var map = L.map('map');
L.tileLayer('http://maps.refuges.info/hiking/{z}/{x}/{y}.png', {
attribution: '© Contributeurs d\'OpenStreetMap',
maxZoom: 18
}).addTo(map);
// An empty base layer
var GeoJSONlayer = L.geoJson().addTo(map);
// Used to only show your area
function onLocationFound(e) {
var radius = e.accuracy / 2;
L.marker(e.latlng).addTo(map);
actualiseGeoJSON();
}
function onLocationError(e) {
alert(e.message);
actualiseGeoJSON();
}
function onMove() {
// map.removeLayer(GeoJSONlayer);
actualiseGeoJSON();
}
map.locate({setView: true, maxZoom: 14});
// Datas are modified if
map.on('locationerror', onLocationError);
map.on('locationfound', onLocationFound);
map.on('moveend', onMove);
I have tried to remove the layer in my first function but GeoJSONlayer is not defined
I have tried to remove the layer in onMove() but nothing appears
I have tried to remove the layer in moveend event but I have an syntax error…
If somebody can help me…
Sorry for my bad English, French guy ith french function names
I see you are using the leaflet ajax plugin.
The simplest way to get your map to work is to download all available data right at the start, providing a giant bounding box, and add it to the map just once. This will probably work just fine, unless there's insanely many cabins and stuff to download.
But if you wish to refresh the data regularly, based on the bounding box, you can use the refresh method in the leaflet-ajax plugin:
you can also add an array of urls instead of just one, bear in mind
that "addUrl" adds the new url(s) to the list of current ones, but if
you want to replace them use refresh e.g.:
var geojsonLayer = L.geoJson.ajax("data.json");
geojsonLayer.addUrl("data2.json");//we now have 2 layers
geojsonLayer.refresh();//redownload those two layers
geojsonLayer.refresh(["new1.json","new2.json"]);//add two new layer replacing the current ones
So initially:
var defaultIcon = ...
function onEachFeature(feature, layer) ...
// Do this in the same scope as the actualiseGeoJSON function,
// so it can read the variable
var GeoJSONlayer = L.geoJson.ajax(
'../exportations/exportations.php?format=geojson&bbox='
+ map.getBounds().toBBoxString() + '',{
onEachFeature: onEachFeature,
pointToLayer: function (feature, latlng) {
return L.marker(latlng, {icon: defaultIcon});
}
}).addTo(map);
And then for each update:
function actualiseGeoJSON() {
// GeoJSONLayer refers to the variable declared
// when the layer initially got added
GeoJSONlayer.refresh(
['../exportations/exportations.php?format=geojson&bbox='
+ map.getBounds().toBBoxString() + '']);
}
Alternatively, you could set the layer as a property of the map, instead of as a var:
map.geoJsonLayer = L.geoJson.ajax(...)
And later refer to it as follows:
map.geoJsonLayer.refresh(...)
this leaflet plugin is more suitable for your purpose, manage map events and zoom.
Caching remote requests and much more.
http://labs.easyblog.it/maps/leaflet-layerjson/
var ajaxUrl = "search.php?lat1={minlat}&lat2={maxlat}&lon1={minlon}&lon2={maxlon}";
map.addLayer( new L.LayerJSON({url: ajaxUrl }) );
Extend L.GeoJSON with more features and support ajax or jsonp request. See the source code comments for more documentation.