I have a circleMarker that I would like to display on top of all other markers.
The marker documentation lists the option zIndexOffset, however circleMarker does not have this attribute.
circleMarker does inherit the pane option from layer, so I thought I could set the marker pane to overlayPane but that is already the default. (see documentation)
I can change the z-index of overlayPane but then all the other feature layers using it will share the same z-index.
Is there a simple way to display a circleMarker on top of other markers/layers?
The solution I found is to create a custom pane for the circle marker and then set the z-index on that pane:
map.createPane("locationMarker");
map.getPane("locationMarker").style.zIndex = 999;
locationMarker = L.circleMarker(e.latlng, { pane: "locationMarker" });
locationMarker.addTo(map);
Related
I have a situation where I have a map with a custom legend formatted as either an SVG or a PNG. The legend is always placed in the bottom left corner but can be quite large (user can turn it off and on).
The map also has many markers. Each marker will have a tooltip, which can also be large-ish. Tooltips show when the mouse is hovering over the marker. The problem arises when a user hovers over a marker close to the legend - the tooltip appears behind the legends. I'd like to make it so the popups appear above the legend. So, from bottom to top: marker, legend, marker popup.
Here is a JSFiddle https://jsfiddle.net/e51mydwa/9/ to describe what I mean. I add the legends in the same way, although the < div id="legend"> tag contains a < img> or < svg> in reality.
<div id="map">
<div id="legend">
I am Legend
</div>
</div>
I've had a look at http://leafletjs.com/examples/choropleth/ , but as you can see by inspecting the DOM, this will suffer the same problem, as the legend is added into the same div as the leaflet controls, which is always above the map layers (as it should be, controls should always be at the top).
I've also tried inserting the legend into a div which is on a sibling layer to the popup containing layer. This fixes the z-index issue, however the parent div of both of these contains a transform which changes as the user drags the map around - meaning the legends change places and aren't static.
Any and all suggestions appreciated.
This requires some heavy hacking, due to the architecture of the Leaflet layers and controls.
One possible approach is to make a custom layer class which stays in a static position, by repositioning its pixel offset at every change of the map's view.
I heartily recommend reading the Leaflet tutorials, in particular the one about map panes and the one about custom layers, to understand how this works.
// Create a 'static' map pane
L.Map.addInitHook(function(){
this.createPane('static');
this.getPane('static').style.zIndex = 675;
});
// Define a custom layer class
L.Layer.StaticOverlay = L.Layer.extend({
onAdd: function(map) {
this._map = map;
var pane = map.getPane('static');
this._container = L.DomUtil.create('div');
pane.appendChild(this._container);
// styling, content, etc
this._container.style.background = 'white';
this._container.style.width = '100px';
this._container.style.height = '50px';
this._container.innerHTML = 'Hi!'
map.on('move zoom viewreset zoomend moveend', this._update, this);
this._update();
},
onRemove: function(map) {
L.DomUtil.remove(this._container);
map.off('move zoom viewreset zoomend moveend', this._update, this);
},
_update: function() {
// Calculate the offset of the top-left corner of the map, relative to
// the [0,0] coordinate of the DOM container for the map's main pane
var offset = map.containerPointToLayerPoint([0, 0]);
// Add some offset so our overlay appears more or less in the middle of the map
offset = offset.add([340, 220]);
L.DomUtil.setPosition(this._container, offset);
}
});
When that's defined, you can simply
var static = new L.Layer.StaticOverlay().addTo(map);
Obviously there are some bits missing, such as how to position the overlay properly (get the map pixel size with getSize(), do the proper arithmetic), and how to set the contents of the overlay with some custom options in the layer constructor.
These are left as an exercise to the reader :-)
See a working example here.
I figured out how to create a polygon in a custom pane using the Working with Map Panes tutorial and this Stack Overflow question with its associated Fiddle.
Can I switch the polygon to a different (custom) pane after it has been created?
I create a polygon in a custom pane like so:
// create custom pane
mymap.createPane('polygonView');
var polygonViewPane = mymap.getPane('polygonView');
polygonViewPane.style.zIndex = 300;
// with custom renderer
var myrenderer = L.svg({
pane: polygonViewPane
});
// create polygon in a custom pane (note the `renderer:myrenderer` or `pane:polygonViewPane` both work)
var myPoly = L.polygon([
[51.509, -0.08],
[51.503, -0.06],
[51.51, -0.047]
], {
fillOpacity: 1,
pane: polygonViewPane
}).addTo(mymap);
It would seem like I should be able to switch the pane with something like:
// changes pane in options.pane, but appearance on the map is same
myPoly.setStyle({pane: polygonViewPaneTop});
// also does not work (command fails without output in console?)
myPoly.setStyle({renderer: myrenderer2});
but neither of these are working. I can switch the zIndex of the whole pane with polygonViewPane.style.zIndex = 800;, but I will usually have multiple polygons on that main pane, and I only want to bring one to the front of all of my layers.
https://jsfiddle.net/kbkxf220/
EDIT:
Updated Fiddle incorporating IvanSanchez's answer:
https://jsfiddle.net/kbkxf220/3/
// THIS WORKS; polygon switches pane and `myPoly.options.pane` shows new pane.
myPoly.removeFrom(mymap);
myPoly.setStyle({pane: polygonViewPaneTop, renderer: myrenderer2});
myPoly.addTo(mymap);
Note that you need to switch renderer for the polygon to switch panes on the map view (see inspect element) and switch pane for myPoly.options.pane to properly display the new pane.
No, Leaflet doesn't allow to change panes on the fly.
Remove the layer from the map, change its options, then re-add it.
If your problem is bringing lines/polygons on top of each other, remember that you can call bringToFront() on them.
I'm trying to put a google.maps.Marker object over (z-index positioning) an Infobubble object
but i am having no success.
Basically what i'm doing is assigning zIndex: n to the markerOptions object which I pass to the Marker constructor as follow:
var markerOptions = {
position: store.getLocation(),
title: store.getDetails().title,
icon: DEFAULT_MARKER,
anchorPoint: new google.maps.Point(20,5),
zIndex: 2
};
var marker = new google.maps.Marker(markerOptions);
I have already read this answer Google Maps v3 marker over infowindow but actually it has not got any votes. Can somebody tell me more about?
Thanks a lot
The problem, as commented by shaunhusain is the fixed pane where particular elements will be drawn.
It's correct that you need to use a custom overlay, but you must use it to draw the marker, not the infobubble.
The reason: infobubble is an implementation of a custom overlay, it will be drawn inside the floatPane. To put the marker on top the infobubble must be drawn into a pane with a zIndex equal or lower than the zIndex of the pane where the marker will be drawn.
But here comes the problem: all these panes do not receive mouse-events, you wouldn't be able to interact with the infobubble(select tabs, select text, click links, close the infobubble).
Therefore you must use a custom overlay to draw the markers, and you must put these overlays into the floatPane(it's the pane with the highest zIndex)
I don't want to the show the layers control on the map, but I want to put some buttons somewhere else to change between layers. Is this possible to change the layer programmatically?
Suppose you have a map:
var map = L.map('worldmap-map').setView([37.8, -96], 4);
To remove a layer, layer1:
map.removeLayer(layer1)
To remove a control layer, ctrlLayer,
map.removeControl(ctrlLayer)
Or you want to add a layer1 to map:
layer1.addTo(map)
For an example, there is a Leaflet example : http://leafletjs.com/examples/choropleth-example.html
You could use firebug or chrome dev tools to see its source.
From https://stackoverflow.com/a/33762133/4355695 : Just myTileLayer.addTo(map) does the job of changing background layer (without adding on top), if it is already part of the base layers. And you don't need to explicitly remove the previously selected background layer.
I have a Google V3 map which uses steetView and some map markers.
The little yellow streetView pegman sits on the map on top of the markers.
Is there a way to change the z-indexes so that my markers will be above the pegman
(so that they can be easlly clicked on without having to zoom in)?
In case anything is not clear, here is a fiddle....
http://jsfiddle.net/spiderplant0/BRkCA/
After a bit of experimenting I came up with this...
$("#map_canvas img[src*=cb_scout]").parent("div").css({'zIndex': -200});
$($("#map_canvas img[src*=cb_scout]")[1]).parent("div").parent("div").css({'zIndex': -200});
This forces the pegman to sit beneath the markers but now the pegman is no longer dragable and each time the map is moved etc, the pegman jumps above the markers again.
To keep the pegman under your markers you can watch for the pov_changed event and reset the z-index after a short delay
$google.maps.event.addListener(panorama, 'pov_changed', function() {
var func=function(){
$("#map_canvas img[src*=cb_scout]").parent("div").css({'zIndex': -200});
}
setTimeout(func,1000);
}
});
You will also need to change the depth of the pegman after the maps moves, which can be accomplished with the following snippet
google.maps.event.addListener(map, 'idle', function() {
google.maps.event.trigger(panorama, 'pov_changed');
})
If you want to be able to drag the pegman, you must first place it above the markers by having a toggle button swap the pegman's depth and add an exception to the pov_changed event handler preventing the pagman from dropping depths when the toggle button is active.
Okay, this may be a bit hacky... (and I hope I understood what you were doing)
1) Disable street view control
2) Make another control with a lower zIndex than the marker you have.
3) Update street view control with the position of the fake street view marker.
http://jsfiddle.net/z7Lp8/
You can set the zIndex of the marker above google.maps.Marker.MAX_ZINDEX in order for the pegman to remain under the marker. MAX_ZINDEX is the maximum default z-index that the API will assign to a marker. Marker z-indexes only work when optimizations are turned off on all markers on the map.
Forked fiddle from question to illustrate: http://jsfiddle.net/brendaz/t4v8nhoq/
var marker1 = new google.maps.Marker({
position: new google.maps.LatLng(54.975, -2.020),
map: map,
zIndex: google.maps.Marker.MAX_ZINDEX + 1,
optimized: false
});