digidem / leaflet-side-by-side

A Leaflet control to add a split screen to compare two map overlays
http://lab.digital-democracy.org/leaflet-side-by-side/
MIT License
351 stars 111 forks source link

[fix] Layers not clipped on change from control layer + iOS buggy interactions #34

Open AHAAAAAAA opened 3 years ago

AHAAAAAAA commented 3 years ago

Thank you again for this wonderful library! I've been using it on my website and wanted to push some fixes. Since this isn't actively maintained, I merged the two fixes into one PR to make it easier for someone to copy the code for their site.

Issue: Changing the overlay or base layer via the control layer resulted in both layers not clipping and appearing on both sides of the divider

This was caused by the new layer not being included in this._leftLayers or this._rightLayers which resulted in this._leftLayer or this._rightLayer being set to null but never getting set again. A null layer would be skipped in _updateClip. I resolved it by adding event handlers to overlayadd and baselayerchange that update this._leftLayer or this._rightLayer to the new layer and then add it to this._leftLayers or this._rightLayers respectively. This allows it to be successfully set and later clipped in _updateClip.

Issue: Leaflet side-by-side not redrawing on drag/move on iOS or requiring 2 fingers to pan or both sides of the map moving independently from the other

This was caused by two issues. iOS handles touchend differently from other platforms. I resolved it by adding an event listener on touchmove instead. This leaves the issue of drag working but only updating one layer until we trigger a redraw by moving the divider or using two fingers to zoom. The clip CSS property was getting set correctly, but iOS Safari/Webkit didn't trigger a redraw of the element when the style property got changed. I resolved it by forcing Safari to redraw with a crude hack (gleaned from this useful page):

sel.style.display='none';
sel.offsetHeight; // no need to store this anywhere, the reference is enough
sel.style.display=''
sefo commented 1 year ago

Tried this. It breaks the range events and no layer is visible. Using Chrome, leaflet 1.9.4 (I did replace getContainer with getPane)