The following code receives an error on the lines for enabling and disabling the marker dragging ("Unable to get property 'disable' of undefined or null reference"). The markers show up on the map just fine and are draggable as the creation line indicates. Placing an alert in place of the enable line produces a proper object so I believe the marker is defined. Is there something I need to do to enable the IHandler interface? Or am I missing something else?
var marker = L.marker(L.latLng(lat,lon), {icon:myIcon, draggable:'true'})
.bindLabel(name, {noHide: true,direction: 'right'});
marker._myId = name;
if (mode === 0) {
marker.dragging.enable();
} else {
marker.dragging.disable();
}
I had a similar problem today (perhaps the same one) it was due to a bug in leaflet (see leaflet issue #2578) where changing the icon of a marker invalidates any drag handling set on that marker. This makes any calls to marker.dragging.disable() fail.
The fix hasn't made it into leaflets master at time of writing. A workaround is to change the icon after updating the draggable status if possible.
marker.dragging.disable();
marker.setIcon(marker_icon);
Use the following code to make an object draggable. Set elementToDrag to the object you wish to make draggable, which is in your case: "marker"
var draggable = new L.Draggable(elementToDrag);
draggable.enable();
To disable dragging, use the following code:
draggable.disable()
A class for making DOM elements draggable (including touch support).
Used internally for map and marker dragging. Only works for elements
that were positioned with DomUtil#setPosition
leaflet: Draggable
If you wish to only disable the drag option of a marker, then you can use the following code (where "marker" is the name of your marker object):
marker.dragging.disable();
marker.dragging.enable();
I haven't found an answer but my workaround was this:
var temp;
if (mode === 0) {
temp = true;
} else {
temp = false;
}
var marker = L.marker(L.latLng(lat,lon), {icon:myIcon, draggable:temp})
.bindLabel(name, {noHide: true,direction: 'right'});
marker._myId = name;
Fortunately I change my icon when it is draggable.
Related
Using Leaflet javascript. I would like my "clear button" to do two things...
1) uncheck all the L.Control layers
2) remove the current overlay from the map
I can do the first easily enough using this code:
var checks = document.querySelectorAll('[type = "checkbox"]'), i;
function uncheckBoxes() {
for (i = 0; i < checks.length; ++i) {
checks[i].checked = false;
}
}
The next is a little more tricky. I have tried using the removeLayer() and clearLayers() function but they do not work. I don't see a way in the leaflet documentation to remove an L.control overlayMap layer from the map unless you physically uncheck it yourself.
Any insight into this would be greatly appreciated.
Not exactly sure what is your difficulty in programmatically removing some layers / overlays from your map.
It is normally trivial (map.removeLayer(layer)), and the Layers Control automatically reflects what is happening on the map (in that case, if layer is one of the overlays, its associated checkbox will become unticked).
As for removing all your overlays from map, you just need to keep a reference to those overlays, loop through them and remove them from the map:
var overlays = {
'Name 1': someLayer,
'Name 2': someOtherLayer
};
L.control.layers(null, overlays).addTo(map);
// Whenever you want to remove all overlays:
for (var name in overlays) {
map.removeLayer(overlays[name]);
}
Demo: https://jsfiddle.net/3v7hd2vx/357/
I'm new to leaflet and am trying to implement a set of markers with different CSS-styles.
So, I am aware that after adding a marker to a map I can access different CSS-attributes by calling getElement() on my marker for example:
marker.addTo(map);
marker.getElement().style.borderColor = '#000';
This works just fine, but when adding a marker to a layer, this can no longer be used since a TypeError occurs (getElement() is undefined). Here is the example code where the error occurs:
myLayer.addLayer(marker);
marker.getElement().style.borderColor = '#000';
Am I overlooking a simpler way to set CSS-Attributes for markers and divicons that are added to layers or is there a similar way to access layer-added markers and divicons in JavaScript?
So I found a solution that is working for me.
The idea is to extend the function that is used to create the icon.
Last answer here github.com/Leaflet/Leaflet/issues/5231 helped a lot.
var borderSize = ...;
L.DivIcon.Custom = L.DivIcon.extend({
createIcon: function(oldIcon) {
var icon = L.DivIcon.prototype.createIcon.call(this, oldIcon);
icon.style.borderSize = borderSize;
...
return icon;
}
})
var icon = new L.DivIcon.Custom({
...
});
var ll = L.latLng(entry.Longitude, entry.Latitude);
var marker = L.marker(ll, {
icon: icon
})
this.myLayer.addLayer(marker);
Welcome to SO!
When not added onto a map (since your parent myLayer may not be added to the map itself), a marker does not have any element.
If you do not need to change too many styles individually and dynamically, you might rather use the className option of your Icon / DivIcon.
Another developer created our original map but I'm tasked with making some changes. One of these is making sure the activated marker is brought to the front when clicked on (where it is partially overlapped by other markers).
The developers have used mapbox 2.2.2.
I have looked at leafletjs's docs, have followed some instructions on other posted solutions (e.g. solution one and solution two). Neither of these makes any difference.
Examining the marker in Chrome's console I can see the value of options.zIndexOffset is being set (10000 in my test case). I've even set _zIndex to an artificially high value and can see that reflected in the marker's data structure. But visually nothing is changing.
This is how the map is set up initially. All features are from a single geojson feed:
L.mapbox.accessToken = '<access token here>';
var map = L.mapbox.map('map', 'map.id', {
}).setView([37.8, -96], 3);
var jsonFeed, jsonFeedURL;
var featureLayer = L.mapbox.featureLayer()
.addTo(map)
.setFilter(function (f) {
return false;
});
$.getJSON(jsonFeedURL, function (json) {
jsonFeed = json;
jsonFeedOld = json;
// Load all the map features from our json file
featureLayer.setGeoJSON(jsonFeed);
}).done(function(e) {
// Once the json feed has loaded via AJAX, check to see if
// we should show a default view
mapControl.activateInitialItem();
});
Below is a snippet of how I had tried setting values to change the z-index. When a visual marker on the featureLayer is clicked, 'activateMarker' is called:
featureLayer.on('click', function (e) {
mapControl.activateMarker(e);
});
The GEOjson feed has urls for the icons to show, and the active marker icon is switched to an alternative version (which is also larger). When the active feature is a single Point I've tried to set values for the marker (lines commented out, some of the various things I've tried!)
activateMarker: function (e) {
var marker = e.layer;
var feature = e.layer.feature;
this.resetMarkers();
if (feature.properties.hasOwnProperty('icon')) {
feature.properties.icon['oldIcon'] = feature.properties.icon['iconUrl'];
feature.properties.icon['iconUrl'] = feature.properties.icon['iconActive'];
feature.properties.icon['oldIconSize'] = feature.properties.icon['iconSize'];
feature.properties.icon['iconSize'] = feature.properties.icon['iconSizeActive'];
}
if (feature.geometry.type == 'Point') {
marker.setZIndexOffset(10001);
marker.addTo(featureLayer);
}
//featureLayer.setGeoJSON(jsonFeed);
}
Any advice would be greatly appreciated! I'm at the point where I don't know what else to try (and that's saying something).
What probably happens is that you just flush your markers with the last call to .setGeoJSON():
If the layer already has features, they are replaced with the new features.
You correctly adjust the GeoJSON data related to your icon, so that when re-created, your featureLayer can use the new values to show a new icon (depending on how you configured featureLayer).
But anything you changed directly on the marker is lost, as the marker is removed and replaced by a new one, re-built from the GeoJSON data.
The "cleanest" way would probably be to avoid re-creating all features at every click.
Another way could be to also change something else in your GeoJSON data that tells featureLayer to build your new marker (through the pointToLayer option) with a different zIndexOffset option.
I have a set of markers that have binded popups, but I can't figure out how to show all the popups when the marker group is toggled in the layers control.
For example, I have my markers like so:
var testMarker = L.marker([32.9076,33.35449]).bindPopup('Marker 1');
var testMarkerTwo = L.marker([33.58259,34.64539]).bindPopup('Marker 2');
Then, I put it in a freature group and append the openPopup method:
var markerGroup = L.featureGroup([testMarker,testMarkerTwo]).openPopup().addTo(map);
This doesn't work.
My final goal is to add that featureGroup to my layers control where I can toggle the group off/on. Before I get to that part, I need to first understand why the openPopup method is not working.
Edit: The answer below appears to only work with the plain Leaflet API, not the Mapbox API.
There are a couple problems here. The first is that by default, Leaflet closes the previously opened popup each time another is opened. The second is that, while your markers have popups bound to them, markerGroup does not, and even if it did, markerGroup.openPopup would only cause a single popup to open.
To get around the first problem, you can use the hack from this answer. If you place the following code at the beginning of your script (before you define your map) it will override the default behavior and allow you to open multiple popups at once:
L.Map = L.Map.extend({
openPopup: function(popup) {
this._popup = popup;
return this.addLayer(popup).fire('popupopen', {
popup: this._popup
});
}
});
Then, once you are able to open multiple popups, you can open all popups in markerGroup using the eachLayer method:
var markerGroup = L.featureGroup([testMarker,testMarkerTwo]).addTo(map);
markerGroup.eachLayer(function(layer) {
layer.openPopup();
});
Here is an example fiddle:
http://fiddle.jshell.net/nathansnider/02gsb1Lt/
I'm building an online version of a boardgame using Leaflet as the viewport.
My source: https://github.com/edenLOL/gotta-chug-em-all/tree/master
What I'm trying to achieve, is a way to spiderfy/spread out markers that land on the same square as each other, including when they move past each other.
I'm using https://github.com/jawj/OverlappingMarkerSpiderfier-Leaflet to Spiderfy the markers, which appears to work when clicking the markers.
However, I need these markers to be spiderfied always, without requiring a click event. So I set keepSpiderfied: true for the spiderfier object (oms).
var options = { //**spiderfier
keepSpiderfied: true,
nearbyDistance: 120
};
oms = new OverlappingMarkerSpiderfier(map, options); //**spiderfier
But this doesn't work. I can't seem to load the markers in a spiderfied state, it always requires a click to spiderfy them.
For context, markers are generated dynamically during a prompt before the user sees the map.
('#playerIcons > table > tbody > tr > td').on('click', function(){
pokemonSelected = $(this).attr('class');
if ( !$(this).hasClass('pokemonSelected') ){
playerArray[pokeCounter].pokemon = ''+ pokemonSelected +'';
playerArray[pokeCounter].marker = L.marker([playerArray[pokeCounter].coords[0], playerArray[pokeCounter].coords[1]], {
icon: window[pokemonSelected]
}).addTo(map);
oms.addMarker(playerArray[pokeCounter].marker) //**spiderfier
pokeCounter += 1;
} else {
return false;
};
});
I've also tried using Leaflet/Leaflet.markercluster. This works to an extent, and spiderfies the Markers at defined zoom levels, however the markers don't move, and stay stacked on top of each other.
What am I missing here that could be causing these issues? I don't mind using either Spiderfier or MarkerCluster, as both should be able to provide the solution I'm looking for once either issue is fixed.
Spiderfier: Markers need to spiderfy automatically
MarkerCluster: Markers don't physically move when spiderfying out of cluster
Note: If you decide to open index.html, be aware the Pokemon theme song will autoplay in the background on page load (until the map is drawn), so check your volume :)
I solve the problem like this, using fire('click') аfrom leaflet.
scope.spiderMarker - the marker, i want to spidrefy. In your case i think its playerArray[pokeCounter].marker
try{
scope.spiderMarker.fire('click')}
catch (e) {
console.log(e);
};