How can I control the zindex of a leaflet layer? - leaflet

I have a codepen at https://codepen.io/ericg_off/pen/qBoPQGX which demonstrates the issue.
I would like the marker to be drawn underneath the line.
How can I change the z-index of the layers to accomplish this?
Searching has suggested several potential solutions, but nothing appears to work.
HTML
<div id="map"></div>
CSS
#map {
height: 100vh;
}
#map >>> .my-icons {
background-color: rgba(0, 255, 0, 0);
}
JS
var map = L.map("map", {
// Set latitude and longitude of the map center (required)
center: [38, -77],
// Set the initial zoom level, values 0-18, where 0 is most zoomed-out (required)
zoom: 5
});
// Create a Tile Layer and add it to the map
var tiles = new L.tileLayer(
"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
{
attribution:
'© OpenStreetMap contributors',
minZoom: 3,
maxZoom: 8
}
).addTo(map);
divIcon = L.divIcon({
//html: '<i class="fa fa-map-marker fa-1x"></i>',
html: '<i class="fa fa-star fa-1x"></i>',
className: 'my-icons'
})
const markerLayer = L.layerGroup().addTo(map);
const lineLayer = L.layerGroup().addTo(map);
// markerLayer.setZIndex(-1000)
// markerLayer.bringToBack();
const from = [38, -77];
const to = [38, -100];
const fromMarker = L.marker(from, { icon: divIcon } ).addTo(lineLayer);
const line = L.polyline([from, to], { color: "green", weight: 1 }).addTo(markerLayer);

The tutorial on panes explains how to change the zIndex of a pane.
After reading the documentation on Panes and learning that the marker pane has a zindex of 600 and the overlay pane (where the lines are drawn) has a index of 400, I just needed to change the marker pane to a index of 300.
map.getPane('markerPane').style.zIndex = 300;
Updated the codepen with the answer.

Related

How can I shift leaflet map bounds without repeating the tiles?

I have a codepen demonstrating the issue at https://codepen.io/ericg_off/pen/KKoJvbK
I am using leaflet 1.8.0.
I have adjusted the map's maxBounds (const maxBounds = [[-90, -480], [90, -120]];) so the left and right edges of the map are
Left Edge ----- Right Edge
To accomplish this, I needed to allow the tileLayer to wrap around the antemeridian...so noWrap retains the default value of true.
So, when I zoom out, I get:
But, I would like to have similar behavior to what would happen if I left the maxBounds set to const maxBounds = [[-90, -180], [90, 180]]; and set noWrap: true which would look like:
i.e. the gray background outside of the maxBounds.
How can I do this?
HTML:
<div id="map"></div>
CSS:
#map {
height: 100vh;
}
JS:
const maxBounds = [
[-90, -480],
[90, -120]
];
// const maxBounds = [
// [-90, -180],
// [90, 180]
// ];
var map = L.map("map", {
center: [38.89, -77.03],
zoom: 3,
maxBounds
});
var tiles = new L.tileLayer(
"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
{
minZoom: 0,
maxZoom: 8,
// noWrap: true
}
).addTo(map);

leaflet draw large number of icon marker

i was use leaflet.js to draw about 10000 icon markers,because it is icon marker,so i cannot use circleMarker. I find a leaflet plugin Leaflet.Canvas-Markers,it can help me draw 10000 icon markers fast, but this plugin caused the click event to fail.
This is my code
var ciLayer = L.canvasIconLayer({}).addTo(leafletMap)
var icon = L.icon({
iconUrl: 'StructWell.png',
iconSize: [20, 18],
iconAnchor: [10, 9]
});
function markerClickHandler (e) {
console.log(e)
console.log()
}
let markers = []
SiteList.results.forEach((site, i) => {
var marker = L.marker([site.latitude, site.longitude], {icon: icon, title: JSON.stringify(site)})
marker.on('click', markerClickHandler)
// ciLayer.addMarker(marker)
markers.push(marker);
})
ciLayer.addLayers(markers);
function markerClickHandler do not work when i click the marker.
was I do some bug,or are there any more solutions. The key is large number of icon markers with click event.
thanks
Listener should be added like below:
ciLayer.addOnClickListener(function (e,data) {
console.log(data)
});
var map = L.map('map').setView([59.9578,30.2987], 10);
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors',
preferCanvas: true
}).addTo(map);
var ciLayer = L.canvasIconLayer({}).addTo(map);
ciLayer.addOnClickListener(function (e,data) {
console.log(data[0].data.mydata)
});
var icon = L.icon({
iconUrl: 'https://img.icons8.com/metro/26/000000/marker.png',
iconSize: [20, 18],
iconAnchor: [10, 9]
});
var markers = [];
for (var i = 0; i < 10000; i++) {
var marker = L.marker([58.5578 + Math.random()*1.8, 29.0087 + Math.random()*3.6], {icon: icon}).bindPopup("I Am "+i);
marker.mydata="I Am "+i
markers.push(marker);
}
ciLayer.addLayers(markers);
.map{
width: 100%;
height: 100px;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.3.1/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet-canvas-marker#0.2.0"></script>
<div class="map" id="map"></div>
You can check examples provided by Leaflet.Canvas-Markers.
Hope this will helps you.

Leaflet Draw preventing click on elements while is active

I have several days fighting this with no luck. I'm using leaflet 1.4.0 along with leaflet.draw 1.0.4. Instead of using the L.control.draw UI, I'm using my own buttons to create polygons and rectangles. It works perfectly on desktop browsers (except IE, of course), but fails on iPads, Android tablets (I've not checked on phones), even if you switch the latest Chrome to emulate a mobile device (using the 'toogle device toolbar' on the dev tools) it fails.
I have created this jsfiddle to illustrate the problem: https://jsfiddle.net/fsv8jegd/2/
Using Chrome with the 'toggle device' off, click on the 'start poly' button. Cursor changes to a cross and a label 'click and drag to draw rectangle'. Click on the 'cancel' button, the cursor goes back to the regular arrow.
Now turn on 'toggle device' on Chrome dev tools and choose 'responsive' or any of the 'iPhone' or 'iPads'. Click on the 'start poly' button. Cursor changes to the cross. Try to click on the 'cancel' button. Nothing happens. It doesn't receive the click event. The only way to cancel this is actually drawing the rectangle.
Any ideas?
Thanks!
html:
<div id="map"> </div>
<button class='buttons' type="button" style="top:0" onclick="startpoly()">START POLY</button>
<button class='buttons' type="button" style="top:20px" onclick="cancelpoly()">CANCEL</button>
css:
#map { height: 200px !important; width: 80%; }
.buttons {position: absolute; left: 0; z-index: 999999}
JS:
polygon_query_options = { shapeOptions: { stroke: true, color: '#6e83f0', weight: 4, opacity: 0.9, fill: true, fillColor: null, fillOpacity: 0.2, clickable: false, dashArray: '10,10' } };
$(document).ready(function() {
map = L.map('map', { preferCanvas: true, zoomControl: true, zoom: 10, maxZoom: 20, center: [29.8, -95.5]});
var drawnItems = new L.FeatureGroup();
drawnItems.addTo(map);
drawnItems.bringToFront();
L.Browser.touch = true;
var baseMapGroup = new L.featureGroup();
basemapLayer = L.tileLayer('https://cartodb-basemaps-d.global.ssl.fastly.net/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', { attribution: 'CartoDB', maxZoom: 20, maxNativeZoom: 20 });
basemapLabelLayer = L.tileLayer('https://cartodb-basemaps-d.global.ssl.fastly.net/rastertiles/voyager_only_labels/{z}/{x}/{y}.png', { attribution: 'CartoDB', maxZoom: 20, maxNativeZoom: 20 });
basemapLabelLayer.addTo(map);
basemapLabelLayer.bringToBack();
basemapLayer.addTo(map);
basemapLayer.bringToBack();
map.on('draw:created', function (e) {
var layer = e.layer;
drawnItems.addLayer(layer);
});
});
function startpoly() {
polygonDrawer = new L.Draw.Rectangle(map, polygon_query_options);
polygonDrawer.enable();
};
function cancelpoly() {
if (polygonDrawer != undefined) { polygonDrawer.disable(); }
};
I found this is a bug on the leaflet.draw library. So I followed the trail, and in the line 1260 of the leaflet.draw 1.0.4 the following code causes the problem:
document.addEventListener('touchstart', L.DomEvent.preventDefault, { passive: false });
I replaced that line with this code:
var tempMap = document.getElementById("map");
tempMap.addEventListener('touchstart', L.DomEvent.preventDefault, { passive: false });
Basically instead of preventing the touchstart event on the document, now is applied only to the map object.
Hope this helps anyone out there.

How to draw a polyline with initial point in Leaflet

I'm using custom polyline drawer from Leaflet.draw
let polylineDrawer = new L.Draw.Polyline(map, {})
polylineDrawer.enable()
I need to programmatically add starting point to polyline
I've tried calling addVertex of L.Draw.Polyline. Looks like it's doesn't work with custom polyline drawer cause of addHooks or something... Tried to change sources, no results.
Also tried firing click on map after drawer is enabled. Like so:
let point = new L.LatLng(x, y)
map.fireEvent('click', {
latlng: point,
layerPoint: map.latLngToLayerPoint(point),
containerPoint: map.latLngToContainerPoint(point),
})
Also doesn't work
EDIT: Actually, AddVertex does work with custom polylines. It "didn't work" because I passed wrong arguments in my function. Somehow, I missed that.
Using addVertex on your drawer object does let you add a starting point to your line :
var polylineDrawer = new L.Draw.Polyline(map, {})
polylineDrawer.enable();
var latlng = L.latLng(48.8583736, 2.2922926);
polylineDrawer.addVertex(latlng);
and a demo
var style = {
stroke: true,
color: 'red',
weight: 4,
opacity: 0.5
};
var map = L.map(document.getElementById('map')).setView([48.8583736, 2.2922926], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
var drawnItems = new L.geoJson(null, {style: style}).addTo(map);
map.on(L.Draw.Event.CREATED, function (event) {
var layer = event.layer;
drawnItems.addLayer(layer);
});
var polylineDrawer = new L.Draw.Polyline(map, {})
polylineDrawer.enable();
var latlng = L.latLng(48.8583736, 2.2922926);
polylineDrawer.addVertex(latlng);
html, body {
height: 100%;
margin: 0;
}
#map {
width: 100%;
height: 100%;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.2.0/dist/leaflet.css" integrity="sha512-M2wvCLH6DSRazYeZRIm1JnYyh22purTM+FDB5CsyxtQJYeKq83arPe5wgbNmcFXGqiSH2XR8dT/fJISVA1r/zQ==" crossorigin=""/>
<script src="https://unpkg.com/leaflet#1.2.0/dist/leaflet.js" integrity="sha512-lInM/apFSqyy1o6s89K4iQUKg6ppXEgsVxT35HbzUupEVRh2Eu9Wdl4tHj7dZO0s1uvplcYGmt3498TtHq+log==" crossorigin=""></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.12/leaflet.draw.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.12/leaflet.draw.js"></script>
<div id='map'></div>

Openlayers draw not scaling correctly to map size

I currently have an openlayers map that I am putting a draw overlay on top of. The problem is that when I scale the div container holding the map it doesn't actually scale the drawing layer correctly, so the pointer does not align with the mouse location. If I don't do any scaling it lines up correctly. I have also tried setting the html and body to 100% width in addition to the div tag, but that has not worked either.
mouse aligned
mouse not aligned
here is my map typesscript code:
// create the bing maps layer
var raster = new ol.layer.Tile({
source: new ol.source.BingMaps({
key: 'AioGchlm6KiMF-8ws9hq9PEJKSZzGXj8aZ1OrDt-MlN_NY907-YdiaraNT9sCodZ',
imagerySet: 'AerialWithLabels',
maxZoom: 19
})
});
// generate the actual map
var map = new ol.Map({
layers: [raster],
target: 'map',
view: new ol.View({
center: [-11000000, 4600000],
zoom: 10
})
});
// holds each of the drawings
var features = new ol.Collection();
// allows the user to draw a polygon on the map
var draw = new ol.interaction.Draw({
features: features,
type: 'Polygon'
});
map.addInteraction(draw);
// adds the polygon to the features collection when the drawing is complete
var featureOverlay = new ol.layer.Vector({
source: new ol.source.Vector({features: features}),
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.2)'
}),
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 2
}),
image: new ol.style.Circle({
radius: 4,
fill: new ol.style.Fill({
color: '#ffcc33'
})
})
})
});
featureOverlay.setMap(map);
// allows the user to modify the drawings
var modify = new ol.interaction.Modify({
features: features,
/*
deleteCondition: function(event) {
return ol.events.condition.shiftKeyOnly(event) &&
ol.events.condition.singleClick(event);
}
*/
});
map.addInteraction(modify);
and the html code:
<div #map id="map"></div>
and the css:
#map {
height: 100%;
}
it is also probably worth noting that I am doing this inside an ionic 3 project.