Leaflet.Sync
Leaflet.Sync copied to clipboard
Offset zoom
What about to support also zoom offset in offsetFn
?
The offsetFn(center, zoom, refMap, tgtMap)
could return:
{
center: L.LatLng,
zoom: number
}
instead of just L.LatLng
, in order to use both center and zoom in the setView()
call of synced map.
Interesting thought, can you show how much change is required?
I did the modification locally for a project I'm working on. There are just a few lines to change (the goolge layer modif is not finished thought). For retro-compatibility & old browser compatibility, the modifications should be adapted.
49c49
< return center;
---
> return { center, zoom };
59a60
> const { center, zoom } = options.offsetFn(this.getCenter(), this.getZoom(), this, map);
61,62c62,63
< options.offsetFn(this.getCenter(), this.getZoom(), this, map),
< this.getZoom(), NO_ANIMATION);
---
> center,
> zoom, NO_ANIMATION);
214,216c215,216
< return toSync.setView(
< originalMap._syncOffsetFns[L.Util.stamp(toSync)](center, zoom, originalMap, toSync),
< zoom, options, true);
---
> const offsetData = originalMap._syncOffsetFns[L.Util.stamp(toSync)](center, zoom, originalMap, toSync);
> return toSync.setView(offsetData.center, offsetData.zoom, options, true);
260c260
< var center = offsetFn(originalMap.getCenter(), originalMap.getZoom(), originalMap, toSync);
---
> const {center, zoom} = offsetFn(originalMap.getCenter(), originalMap.getZoom(), originalMap, toSync);
Well, I didn't check everything : when I pan the map it should move according to the zoom difference. There is also the offsetHelper function to update.
Ok, so here is a version that handles :
- pan with keyboard arrows
- pan with mouse
- offsetHelper with both offset and zoom (added zoomDiff argument, ex : -2 : the synced map will have zoom 3 when the original map has zoom 5)
There is a very little modification to make google layer work. Do you want to integrate this ?
Regards
21c21
< L.Sync.offsetHelper = function (ratioRef, ratioTarget) {
---
> L.Sync.offsetHelper = function (ratioRef, ratioTarget, zoomDiff) {
23a24
> var zoomFactor = Math.pow((zoomDiff > 0) ? .5 : 2, Math.abs(zoomDiff));
24a26,27
> var targetZoom = zoom + zoomDiff;
> var ot2 = zoomFactor == 1 ? ot : ot.map(val => ((val-.5) * zoomFactor)+.5);
29,30c32,33
< .add([(0.5 - ot[0]) * ts.x, (0.5 - ot[1]) * ts.y]);
< return refMap.unproject(pt, zoom);
---
> .add([(0.5 - ot2[0]) * ts.x, (0.5 - ot2[1]) * ts.y]);
> return { center: refMap.unproject(pt, zoom), zoom: targetZoom };
49c52
< return center;
---
> return { center, zoom };
59a63
> const { center, zoom } = options.offsetFn(this.getCenter(), this.getZoom(), this, map);
61,62c65,66
< options.offsetFn(this.getCenter(), this.getZoom(), this, map),
< this.getZoom(), NO_ANIMATION);
---
> center,
> zoom, NO_ANIMATION);
152a157,167
> _zoomFactorTo: function(syncedMap) {
> const zoom = this.getZoom();
> const toSyncZoom = syncedMap.getZoom();
> if (zoom == toSyncZoom) {
> return 1;
> }
> const zoomDiff = zoom - toSyncZoom;
> const zoomFactor = Math.pow((zoomDiff > 0) ? .5 : 2, Math.abs(zoomDiff));
> return zoomFactor;
> },
>
214,216c229,230
< return toSync.setView(
< originalMap._syncOffsetFns[L.Util.stamp(toSync)](center, zoom, originalMap, toSync),
< zoom, options, true);
---
> const offsetData = originalMap._syncOffsetFns[L.Util.stamp(toSync)](center, zoom, originalMap, toSync);
> return toSync.setView(offsetData.center, offsetData.zoom, options, true);
227c241,243
< toSync.panBy(offset, options, true);
---
> const zoomFactor = originalMap._zoomFactorTo(toSync);
> const newOffset = (zoomFactor == 1 || ! Array.isArray(offset)) ? offset : offset.map(o => o*zoomFactor);
> toSync.panBy(newOffset, options, true);
255,256c271,278
< originalMap._syncMaps.forEach(function (toSync) {
< L.DomUtil.setPosition(toSync.dragging._draggable._element, self._newPos);
---
> originalMap._syncMaps.forEach(function (toSync)
> {
> let newPos = self._newPos;
> const zoomFactor = originalMap._zoomFactorTo(toSync);
> if (zoomFactor != 1) {
> newPos = newPos.multiplyBy(zoomFactor);
> }
> L.DomUtil.setPosition(toSync.dragging._draggable._element, newPos);
260c282
< var center = offsetFn(originalMap.getCenter(), originalMap.getZoom(), originalMap, toSync);
---
> const {center, zoom} = offsetFn(originalMap.getCenter(), originalMap.getZoom(), originalMap, toSync);
Few comments:
- In those changes you are using syntax from ES6, like
const
. That means the you need a transpilation to ES5. As the rest of the plugin (and Leaflet I guess) is already in ES5, you should use that syntax instead. - those changes will break API compatibility. This means a change in the mayor version?
- I guess (I have never tried it) Leaflet supports non integer zooms. Are you supporting it?
It is possible to keep compatibility, however offsetFn
returning a value center
or an object {center, zoom}
might be counter-intuitive.
I didn't try to write something compatible with ES5 (I just share the code I use), but is can be easily fixed.
I just saw that leaflet supports fractional zoom, I didn't try to support it. There are glitches on basic maps with fractional zoom tests (white lines visible between tiles) without the sync plugin, I wont't test it further