How to collapse the leaflet control - leaflet

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();
});

Related

adding additional layers to existing toggle visibility buttons

I have pieced together the following code using examples on Mapbox... https://codepen.io/charlie-enright/pen/ZExKOGB?editors=0010
What I want to do now is add another raster layer but have its visibility controlled by one of the existing buttons (the "geophys")button rather than to have to add an extra button.
Is it possible to have two separate raster layers controlled by the same toggle button with the script I have used? If so how will I go about doing this?
The code for the additional raster layer I want to add to be controlled by the geophys button is:
map.addSource('rudbaxton', {
'type': 'raster',
'url': 'mapbox://charlie-enright.chlrzasw'
});
map.addLayer({
'id': 'geophys1',
'source': 'rudbaxton',
'type': 'raster'
});
On top of this I would like the opacity control to adjust the opacity for the two raster layers controlled by the "geophys" button. is this possible to do as well?
Thanks,
The way the example you used is set up, the text in the button must exactly match the name of the layer you want to toggle.
This line gets the text from the button that was clicked:
const clickedLayer = this.textContent;
This line gets the current visibility of the layer with the same name const visibility = map.getLayoutProperty(clickedLayer, "visibility");`
To control two layers with one button click, you just need to add some logic to check for which button was clicked, and respond accordingly:
link.onclick = function (e) {
const clickedButtonText = this.textContent;
e.preventDefault();
e.stopPropagation();
if (clickedButtonText === "geophys") {
// assuming your two layers should always be on or off together, only check the current visibility of one of them
const visibility = map.getLayoutProperty("some-first-layer", "visibility");
// Toggle layer visibility by changing the layout object's visibility property.
if (visibility === "visible") {
map.setLayoutProperty("some-first-layer", "visibility", "none");
map.setLayoutProperty("some-second-layer", "visibility", "none");
this.className = "";
} else {
this.className = "active";
map.setLayoutProperty("some-first-layer", "visibility", "visible");
map.setLayoutProperty("some-second-layer", "visibility", "visible");
}
}
// repeat the above if statement for the other button(s)
};
As a bonus, this means you can use any text you want in the buttons, which might be a little more human-friendly than using the layer names!

How to add popup or bind popup to a point/marker in Leaflet FlowMap without breaking the 'flow' display?

I am using the following leaflet plugin:
https://github.com/jwasilgeo/Leaflet.Canvas-Flowmap-Layer
I am having issues adding a popup to the map when a user clicks on a point.
L.marker([pts[p].lat, pts[p].lng], {
icon: new L.DivIcon({
html: '<div>Test</div>'
})
}).addTo(map).bindPopup('A pretty CSS3 popup.<br> Easily customizable.')
.openPopup();
The popup shows, but I am unable to get the actual flowmap lines to show up. Is there anyway to allow for a popup and to allow for the lines to show up underneath it?
You can use the fact that the CanvasFlowmapLayer extends L.GeoJSON
You just need to overload the method creating the marker and add your popup there ...
var oneToManyFlowmapLayer = L.canvasFlowmapLayer(geoJsonFeatureCollection, {
pointToLayer: function(geoJsonPoint, latlng) {
var marker = L.circleMarker(latlng);
return marker.bindPopup('' + latlng)
},
// et caetera
Check it out here: https://yafred.github.io/Leaflet.Canvas-Flowmap-Layer/docs/main/

Change leafletLayers after a dragend event

I need to delete all the leafletLayers and add others after a 'dragend' event. So, i proceeded as below :
mapParent.component
template: '<app-map [leafLetmarkers]="markers" (refreshMap)="refresh($event)"></app-map>'
...
markers: L.Layer[] = [];
refresh(position) {
//delete all markers
var markers = [];
//set the new markers
this.markers= newMarkers;
}
map.component
template: '<div leaflet style="height: 100%;"
[leafletOptions]="options"
[leafletLayers]="markers"
(leafletMapReady)="onMapReady($event)">
</div>'
...
#Input('leafLetmarkers') markers: L.Layer[];
#Output() refreshData = new EventEmitter<L.LatLng>();
onMapReady(map: L.Map) {
map.on('dragend', e => this.refreshMap.emit(map.getCenter()));
}
Is this the right way to do this ?
Regards.
Your general approach is correct.
The issue you might run into is that you are changing a bound property this.markers inside of a callback from Leaflet. Leaflet callbacks are outside of the Angular zone (Angular doesn't try to track changes outside of its zone). This is a design choice on the part of ngx-leaflet to prevent excessive change detection that might impact application performance.
The solution is to manually trigger change detection:
fitBounds: any = null;
circle = circle([ 46.95, -122 ], { radius: 5000 });
// Inject the Change Detector into your component
constructor(private changeDetector: ChangeDetectorRef) {}
ngOnInit() {
// The 'add' event callback happens outside of the Angular zone
this.circle.on('add', () => {
// Because we're outside of Angular's zone, this change won't be detected
this.fitBounds = this.circle.getBounds();
// But, it will if we tell Angular to detect changes
this.changeDetector.detectChanges();
});
}
For more details, you can see this section of the ngx-leaflet README:
https://github.com/Asymmetrik/ngx-leaflet#a-note-about-change-detection

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.

Avoid Ext.form validation scrolling to top

I have a Ext.form.Panel inside Ext.window. Form height is more than window height so I have vertical scroll on window.
On form fields validation (on validitychange event) scroll jumps to the top.
How to avoid this behaviour?
I tried to figure out, why one of my forms did scroll up and other did not. Turned out, that I have forgot to explicitly specify layout manager and that default layout manager (anchor) scrolled to top on validity change, while vbox layout did not. While everything looked exactly the same (vbox with align: 'stretch'), it behaved differently when the error was either shown or hidden.
I have the same problem :(
I made a creepy workaround (it works to 80%) Sometimes it still jumps to the top.
You should know, that I have a window with a layout of 'form'. If you have a window with (for example) a layout of 'fit' with an xtype of 'form' - you may have to change the code a little bit.
For example the line el.child(".x-window-body", fasle) wouldn't work.
init: function() {
this.control({
...
/** My Ext.window.Window is called reservationwindow **/
'reservationwindow': {
afterrender: function(comp) {
// comp is this Ext.Component == wrapper
var el = comp.getEl();
//extjs adds the scrollbar to the body element...
var elForm = el.child(".x-window-body", false);
// or el.child(".x-panel-body", false);
//we are listinig to the scroll-event now
this.myFormEl = elForm;
this.safeScroll = {top:0, left:0};
elForm.on('scroll', function() {
console.log("save");
this.safeScroll = this.myFormEl.getScroll();
}, this);
elForm.on('click', function() {
var resWin = this.getResWin();
resWin.scrollBy(0,this.safeScroll.top,false);
console.log("reset");
}, this);
elForm.on('keyup', function() {
var resWin = this.getResWin();
resWin.scrollBy(0, this.safeScroll.top, false);
console.log("reset");
}, this);
}
As you can see, I am listening to the scroll-event and safe and reset the scroll bar. Sometimes (especially if you are writing very quickly in a textbox) the events come in a different order and the page will still jump to the top. Sometimes you also see it flickering around (if it needs too long to set it back to the original position).
So.... As I said, its a creepy workaround.
If you find a better solution, please let me know.
EDIT
I also figured out, that the grow option on a textareafield was one of the troublemakers.
{
id: this.id + '-details',
xtype: 'textareafield',
// grow: true, now it isn't jumping
name: 'message',
fieldLabel: 'Zusätzliche Informationen',
labelAlign: 'top',
renderder: 'htmlEncode',
disabled: isDisabled,
anchor: '100%'
}