Leaflet, how to put overlays above basemaps in control? - leaflet

In Leaflet control are overlays under basemaps. How to put them up?
Just to swap position of overlayers/basemaps.

Edit, now with flex:
.leaflet-control-layers-expanded .leaflet-control-layers-list {
display:flex; flex-direction:column;}
.leaflet-control-layers-base { order:3 }
.leaflet-control-layers-separator {order:2}
Older:
.leaflet-control-layers-list {display:table; }
.leaflet-control-layers-base {display:table-footer-group; }
.leaflet-control-layers-overlays {display:table-header-group;}
.leaflet-control-layers-separator {display:none}
from:
CSS table rows reorder

Related

How to collapse the leaflet control

I start my application with expand Layer-Control:
L.control.layers(baseMaps, overlays, { collapsed:false } ).addTo(mymap);
I found no Mouse-Action to minimize the Layer-Control. I want to minimize the Layer-Control. But I don't know the handler. Could anybody give me a tip?
I had the same requirement for Leaflet. I needed to have the layer control expanded at first and then return to its normal hiding after someone realizes what it does.
I am using JQuery, but you could probably manipulate the DOM as well.
I have a function that instantiates the layer control object, and then I immediately reset the mouseenter and mouseleave events for the expanded control and the smaller toggle widget.
let layerControl = L.control.layers(basemap_items, { 'specialLayer': layer}, { collapsed: false }).addTo(map);
$('.leaflet-control-layers').on('mouseleave', () => {
layerControl.collapse();
});
$('.leaflet-control-layers-toggle').on('mouseenter', () => {
layerControl.expand();
});

Styling MapBox GL Markers

I am trying to move from using Mapbox.js with Leaflet to Mapbox GL.
I have the following geojson that should be rendered as per the image attached. Unfortunately, after reading many articles and through the documentation related to data driven visualisation I've hit a wall. Wondered if anyone could help with an example?!
Here's the geojson:
{ "type":"Feature",geometry: { "type":"Point","coordinates":[1.1147,51.7829] },properties: { "title":"Paul","marker-color":"#0094F7","marker-size":"large","marker-symbol":"star" } },
{ "type":"Feature",geometry: { "type":"Point","coordinates":[-2.34851,52.6123] },properties: { "title":"Will","marker-color":"#F9883E","marker-size":"large","marker-symbol":"1" } },
{ "type":"Feature",geometry: { "type":"Point","coordinates":[-2.76389,53.0232] },properties: { "title":"Mark","marker-color":"#F1574E","marker-size":"large","marker-symbol":"13" } },
{ "type":"Feature",geometry: { "type":"Point","coordinates":[-.127211,51.6014] },properties: { "title":"David","marker-color":"#83C736","marker-size":"large","marker-symbol":"20" } },
{ "type":"Feature",geometry: { "type":"Point","coordinates":[-2.06682,53.4986] },properties: { "title":"Adam","marker-color":"#FC5C53","marker-size":"large","marker-symbol":"rocket" } }
The colour values are set by the end user and could be anything so I can't just create a lot of images to suit, and the numbers refer to dates so will be 1-31.
Here's what it currently looks like in Mapbox.js:
Thanks all!
Using Markers, you have full control to display any HTML element you like - so you could use CSS to construct a circle or teardrop of the right color, or an SVG icon.
See this example: https://www.mapbox.com/mapbox-gl-js/example/custom-marker-icons/
Essentially, instead of adding the GeoJSON directly as a source into the map, you will want to iterate over each point, and add markers onto the map.

How to set the zIndex layer order for geoJson layers?

I would like to have certain layers to be always on top of others, no matter in which order they are added to the map.
I am aware of bringToFront(), but it does not meet my requirements. I would like to set the zIndex dynamically based on properties.
Leaflet has the method setZIndex(), but this apparently does not work for geoJson layers:
https://jsfiddle.net/jw2srhwn/
Any ideas?
Cannot be done for vector geometries.
zIndex is a property of HTMLElements, and vector geometries (lines and polygons) are rendered as SVG elements, or programatically as <canvas> draw calls. Those two methods have no concept of zIndex, so the only thing that works is pushing elements to the top (or bottom) of the SVG group or <canvas> draw sequence.
Also, remind that L.GeoJSON is just a specific type of L.LayerGroup, in your case containing instances of L.Polygon. Furthermore, if you read Leaflet's documentation about the setZIndex() method on L.LayerGroup:
Calls setZIndex on every layer contained in this group, passing the z-index.
So, do L.Polygons have a setZIndex() method? No. So calling that in their containing group does nothing. It will have an effect on any L.GridLayers contained in that group, though.
Coming back to your problem:
I would like to have certain layers to be always on top of others, no matter in which order they are added to the map.
Looks like the thing you're looking for is map panes. Do read the map panes tutorial.
This is one of the reason for the implementation of user defined "panes" in Leaflet 1.0 (compared to versions 0.x).
Create panes: var myPane = map.createPane("myPaneName")
If necessary, set the class / z-index of the pane element: myPane.style.zIndex = 450 (refer to z-index values of built-in panes)
When creating your layers, specify their target pane option: L.rectangle(corners, { pane: "myPaneName" })
When building through the L.geoJSON factory, you can loop through your features with the onEachFeature option to clone your layers with specified target pane.
Demo: https://jsfiddle.net/3v7hd2vx/90/
For peoples who are searching about Z-Index
All path layers (so all except for markers) have no z-index because svg layers have a fix order. The first element is painted first. So the last element is painted on top.
#IvanSanchez described good why zIndex not working.
You can control the order with layer.bringToBack() or layer.bringToFront().
With that code you have more options to control the order of the layers.
L.Path.include({
getZIndex: function() {
var node = this._path;
var index = 0;
while ( (node = node.previousElementSibling) ) {
index++;
}
return index;
},
setZIndex: function(idx) {
var obj1 = this._path;
var parent = obj1.parentNode;
if(parent.childNodes.length < idx){
idx = parent.childNodes.length-1;
}
var obj2 = parent.childNodes[idx];
if(obj2 === undefined || obj2 === null){
return;
}
var next2 = obj2.nextSibling;
if (next2 === obj1) {
parent.insertBefore(obj1, obj2);
} else {
parent.insertBefore(obj2, obj1);
if (next2) {
parent.insertBefore(obj1, next2);
} else {
parent.appendChild(obj1);
}
}
},
oneUp: function(){
this.setZIndex(this.getZIndex()+1)
},
oneDown: function(){
this.setZIndex(this.getZIndex()-1)
}
});
Then you can call
polygon.oneUp()
polygon.oneDown()
polygon.setZIndex(2)
polygon.getZIndex()
And now layergroup.setZIndex(2) are working

How to use out side leaflet.draw control with leaflet.snap?

First of all I would like to thank you all for amazing libraries like leaflet/leaflet.draw and leaflet.snap.
What I want to do is outside leaflet.draw control with supporting leaflet snap. This is nicely working with in side map draw control.
Below I show how did I call outside leaflet draw control:
<div><button id="draw_mark1" onclick="drawMarker1()" >Draw Marker1</button></div>
<div><button id="draw_polyline1" onclick="drawPolyline1()" >Draw Polyline1</button></div>
function drawMarker1(){
var markerDrawer1 = new L.Draw.MarkerA(map, { icon: new myIcon_xx() });
markerDrawer1.enable();
}
function drawPolyline1(){
var polylineDrawer1 = new L.Draw.PolylineType1(map);
polylineDrawer1.enable();
}
note:- leaflet.snap not in the tag list. I want to tag it too.

jqPlot- issue with displaying bar charts -axis padding and inter-bar distance

I'm using the following piece of code to display a set of bar charts in jqPlot. However, I am getting 2 problems:
There is no padding on either side of the range values for the xaxis. The pad attribute seems to have no effect.
When the number of bars is large, the bars overlap on top of each other. The barPadding attribute seems to have no effect.
I looked at this link Having problems with jqPlot bar chart . The answer suggested there was to use a CategoryAxisRenderer. But since I'm using time-series data, I require the DateAxisRenderer.
Please help.
function plotBarGraph(data,myticks,series)
{
$("#placeholder").empty();
$.jqplot('placeholder',data,
{
//stackSeries:true,
seriesDefaults:{
renderer:$.jqplot.BarRenderer,
barMargin:1,
barPadding:0.5
},
axes:
{
xaxis:
{
ticks:myticks,
tickInterval:10,
renderer:$.jqplot.DateAxisRenderer,
pad:2.5,
tickOptions:
{
formatString:'%d-%m-%y'
}
}
},
legend:
{
show:true,
labels:series
}
});
}
In this case if you do not want to use the approach mentioned in the link, you might want to play with min/max values for your date axis.
I think you might also find useful the approach to a similar sort of problem with padding where I chose to set ticks on creation and hide the unwanted ones after the plot is drawn.
Before I can be of any further assistance please provide a sample presenting your problem.
For your second problem, I ran into a similar issue. I set up a selection statement that widened the size of my chart depending on how many bars would be in it. I then made the parent div scrollable (called "dataHolder"), and that solved the problem.
// set div properties depending on how many sets of data are in the
//array so the view is sized properly
$("#chartDiv").html("").css("width", "750px"); // chartDiv's default settings
$("#tabs-6").removeClass("dataHolder").css("width", "900px"); // parent Div's default settings
if (dataArray.length > 10) {
$("#chartDiv").css("width", "1600px");
$("#tabs-6").addClass("dataHolder").css("width", "900px");
} else if (dataArray.length > 6) {
$("#chartDiv").css("width", "1200px");
$("#tabs-6").addClass("dataHolder").css("width", "900px");
}
I found a solution to use Date data with CategoryAxisRenderer. You have to configure de xaxis like follows:
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
rendererOptions: {
tickRenderer: $.jqplot.DateTickRenderer,
tickOptions: {
formatter: $.jqplot.DateTickFormatter,
formatString:'%d/%m'
}
}
}
}
I hope it helps! ;)