commit dc647e828892011bc9ddf6b6fd608383e3139f98
parent 2b608371c9351e7e880bfa58c008f0875239fdd2
Author: Sergej Orlov <wladimirych@gmail.com>
Date:   Sun, 28 Oct 2018 22:44:48 +0100
reposition markers and vector objects to be visible when scrolling map 360 degress and after worldJump  #140
Diffstat:
1 file changed, 82 insertions(+), 0 deletions(-)
diff --git a/src/lib/leaflet.fixes/index.js b/src/lib/leaflet.fixes/index.js
@@ -6,6 +6,9 @@ function fixAll() {
     fixTouchDetection();
     fixMapKeypressEvent();
     fixVectorDrawWhileAnimation();
+    fixVectorWorldJump();
+    fixMarkerWorldJump();
+    fixViewResetOnWorldJump();
 }
 
 // https://github.com/Leaflet/Leaflet/issues/3575
@@ -78,4 +81,83 @@ function fixVectorDrawWhileAnimation() {
     L.Renderer.__animationFixed = true;
 }
 
+function fixVectorWorldJump() {
+    // Shift line points longitude by +360 or -360, to minimize distance between line center and map view center
+    // Longitude is changed only for display, longitude of pints is not changed
+    // Breaks dipslay of lines spanning more then one world copy
+    L.Polyline.prototype._projectLatlngs = function(latlngs, result, projectedBounds) {
+        var flat = latlngs[0] instanceof L.LatLng,
+            len = latlngs.length,
+            i, ring;
+        const polylineBounds = this.getBounds();
+        let shift = 0;
+        if (polylineBounds.isValid()) {
+            const worldWidth = this._map.getPixelWorldBounds().getSize().x;
+            const polylineCenter = polylineBounds.getCenter();
+            const mapCenter = this._map.getCenter();
+
+            if (polylineCenter.lng < mapCenter.lng - 180) {
+                shift = worldWidth
+            } else if (polylineCenter.lng > mapCenter.lng + 180) {
+                shift = -worldWidth;
+            }
+        }
+
+        if (flat) {
+            ring = [];
+            for (i = 0; i < len; i++) {
+                let p = this._map.latLngToLayerPoint(latlngs[i]);
+                p.x += shift;
+                ring[i] = p;
+                projectedBounds.extend(p);
+            }
+            result.push(ring);
+        } else {
+            for (i = 0; i < len; i++) {
+                this._projectLatlngs(latlngs[i], result, projectedBounds);
+            }
+        }
+    }
+}
+
+function fixMarkerWorldJump() {
+    // Shift marker longitude by +360 or -360, which is closer to map view center
+    // Longitude is changed only for positioning html-element, Marker._latlng is not changed
+    // Breaks display of markers with huge longitudes like 750 (can be displayed only at zoom levels 0 or 1)
+    L.Marker.prototype.update = function() {
+        if (this._icon) {
+            const mapCenter = this._map.getCenter();
+            const worldWidth = this._map.getPixelWorldBounds().getSize().x;
+            var pos = this._map.latLngToLayerPoint(this._latlng).round();
+            if (this._latlng.lng < mapCenter.lng - 180) {
+                pos.x += worldWidth
+            } else if (this._latlng.lng > mapCenter.lng + 180) {
+                pos.x -= worldWidth;
+            }
+            this._setPos(pos);
+        }
+
+        return this;
+    };
+}
+
+function fixViewResetOnWorldJump() {
+    L.Map.addInitHook(function() {
+        this._lastResetLongitude = null;
+        this.on('viewreset', () => {
+            this._lastResetLongitude = this.getCenter().lng;
+        });
+
+        this.on('move', (e) => {
+            const lng = this.getCenter().lng;
+            if (this._lastResetLongitude === null) {
+                this._lastResetLongitude = lng;
+            } else if (Math.abs(lng - this._lastResetLongitude) > 90) {
+                this.fire('viewreset');
+            }
+        })
+    });
+}
+
+
 export {fixAll}