[Pkg-javascript-commits] [leaflet-markercluster] 16/128: Merge remote-tracking branch 'upstream/leaflet-master-merge' into leaflet-master-merge

Jonas Smedegaard dr at jones.dk
Sun Apr 16 06:25:59 UTC 2017


This is an automated email from the git hooks/post-receive script.

js pushed a commit to branch master
in repository leaflet-markercluster.

commit 1a7d012cdd768d3436249d14544e3be5584b8cca
Merge: 5fcd073 d1b11d9
Author: ghybs <ghybs1 at gmail.com>
Date:   Mon Nov 16 14:39:47 2015 +0400

    Merge remote-tracking branch 'upstream/leaflet-master-merge' into leaflet-master-merge
    
    Conflicts:
    	src/MarkerCluster.Spiderfier.js
    	src/MarkerClusterGroup.js

 package.json                    |  2 +-
 src/MarkerCluster.Spiderfier.js | 21 ++++++++++++++
 src/MarkerClusterGroup.js       | 64 +++++++++++++++++++++++++++++------------
 3 files changed, 68 insertions(+), 19 deletions(-)

diff --cc src/MarkerCluster.Spiderfier.js
index 3430fd0,99ba453..60fca8a
--- a/src/MarkerCluster.Spiderfier.js
+++ b/src/MarkerCluster.Spiderfier.js
@@@ -124,12 -125,11 +127,14 @@@ L.MarkerClusterNonAnimated = L.MarkerCl
  		var group = this._group,
  			map = group._map,
  			fg = group._featureGroup,
 +			legOptions = this._group.options.spiderLegPolylineOptions,
  			i, m, leg, newPos;
  
+ 		group._ignoreMove = true;
+ 
 -		for (i = childMarkers.length - 1; i >= 0; i--) {
 +		// Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition.
 +		// The reverse order trick no longer improves performance on modern browsers.
 +		for (i = 0; i < childMarkers.length; i++) {
  			newPos = map.layerPointToLatLng(positions[i]);
  			m = childMarkers[i];
  
@@@ -146,70 -140,45 +151,74 @@@
  			}
  
  			fg.addLayer(m);
 -
 -			var legOptions = this._group.options.spiderLegPolylineOptions;
 -			leg = new L.Polyline([this._latlng, newPos], legOptions);
 -			map.addLayer(leg);
 -			m._spiderLeg = leg;
  		}
  		this.setOpacity(0.3);
+ 
+ 		group._ignoreMove = false;
  		group.fire('spiderfied');
  	},
  
  	_animationUnspiderfy: function () {
  		this._noanimationUnspiderfy();
  	}
 -} : {
 -	//Animated versions here
 -	SVG_ANIMATION: (function () {
 -		return document.createElementNS('http://www.w3.org/2000/svg', 'animate').toString().indexOf('SVGAnimate') > -1;
 -	}()),
 +});
 +
 +//Animated versions here
 +L.MarkerCluster.include({
  
  	_animationSpiderfy: function (childMarkers, positions) {
 -		var me = this,
 -			group = this._group,
 +		var group = this._group,
  			map = group._map,
  			fg = group._featureGroup,
 -			thisLayerPos = map.latLngToLayerPoint(this._latlng),
 -			xmlns = 'http://www.w3.org/2000/svg',
 -			i, m, leg, newPos;
 +			thisLayerLatLng = this._latlng,
 +			thisLayerPos = map.latLngToLayerPoint(thisLayerLatLng),
 +			svg = L.Path.SVG,
 +			legOptions = L.extend({}, this._group.options.spiderLegPolylineOptions), // Copy the options so that we can modify them for animation.
 +			finalLegOpacity = legOptions.opacity,
 +			i, m, leg, legPath, legLength, newPos;
 +
 +		if (finalLegOpacity === undefined) {
 +			finalLegOpacity = L.MarkerClusterGroup.prototype.options.spiderLegPolylineOptions.opacity;
 +		}
 +
 +		if (svg) {
 +			// If the initial opacity of the spider leg is not 0 then it appears before the animation starts.
 +			legOptions.opacity = 0;
 +
 +			// Add the class for CSS transitions.
 +			legOptions.className = (legOptions.className || '') + ' leaflet-cluster-spider-leg';
 +		} else {
 +			// Make sure we have a defined opacity.
 +			legOptions.opacity = finalLegOpacity;
 +		}
  
+ 		group._ignoreMove = true;
+ 
 -		//Add markers to map hidden at our center point
 -		for (i = childMarkers.length - 1; i >= 0; i--) {
 +		// Add markers and spider legs to map, hidden at our center point.
 +		// Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition.
 +		// The reverse order trick no longer improves performance on modern browsers.
 +		for (i = 0; i < childMarkers.length; i++) {
  			m = childMarkers[i];
  
 -			//If it is a marker, add it now and we'll animate it out
 +			newPos = map.layerPointToLatLng(positions[i]);
 +
 +			// Add the leg before the marker, so that in case the latter is a circleMarker, the leg is behind it.
 +			leg = new L.Polyline([thisLayerLatLng, newPos], legOptions);
 +			map.addLayer(leg);
 +			m._spiderLeg = leg;
 +
 +			// Explanations: https://jakearchibald.com/2013/animated-line-drawing-svg/
 +			// In our case the transition property is declared in the CSS file.
 +			if (svg) {
 +				legPath = leg._path;
 +				legLength = legPath.getTotalLength() + 0.1; // Need a small extra length to avoid remaining dot in Firefox.
 +				legPath.style.strokeDasharray = legLength + ' ' + legLength;
 +				legPath.style.strokeDashoffset = legLength;
 +			}
 +
 +			// If it is a marker, add it now and we'll animate it out
  			if (m.setOpacity) {
 -				m.setZIndexOffset(1000000); //Make these appear on top of EVERYTHING
 +				m.setZIndexOffset(1000000); // Make normal markers appear on top of EVERYTHING
  				m.clusterHide();
  			
  				fg.addLayer(m);
@@@ -237,17 -207,64 +246,19 @@@
  				m.clusterShow();
  			}
  
 -
 -			//Add Legs.
 -			var legOptions = this._group.options.spiderLegPolylineOptions;
 -			if (legOptions.opacity === undefined) {
 -				legOptions.opacity = initialLegOpacity;
 -			}
 -			leg = new L.Polyline([me._latlng, newPos], legOptions);
 -
 -			map.addLayer(leg);
 -			m._spiderLeg = leg;
 -
 -			//Following animations don't work for canvas or browsers that don't support animated svg
 -			if (this.SVG_ANIMATION) {
 -				//How this works:
 -				//http://stackoverflow.com/questions/5924238/how-do-you-animate-an-svg-path-in-ios
 -				//http://dev.opera.com/articles/view/advanced-svg-animation-techniques/
 -
 -				//Animate length
 -				var length = leg._path.getTotalLength();
 -				leg._path.setAttribute("stroke-dasharray", length + "," + length);
 -
 -				var anim = document.createElementNS(xmlns, "animate");
 -				anim.setAttribute("attributeName", "stroke-dashoffset");
 -				anim.setAttribute("begin", "indefinite");
 -				anim.setAttribute("from", length);
 -				anim.setAttribute("to", 0);
 -				anim.setAttribute("dur", 0.25);
 -				leg._path.appendChild(anim);
 -				anim.beginElement();
 -
 -				//Animate opacity
 -				anim = document.createElementNS(xmlns, "animate");
 -				anim.setAttribute("attributeName", "stroke-opacity");
 -				anim.setAttribute("attributeName", "stroke-opacity");
 -				anim.setAttribute("begin", "indefinite");
 -				anim.setAttribute("from", 0);
 -				anim.setAttribute("to", 0.3);
 -				anim.setAttribute("dur", 0.25);
 -				leg._path.appendChild(anim);
 -				anim.beginElement();
 +			// Animate leg (animation is actually delegated to CSS transition).
 +			if (svg) {
 +				leg = m._spiderLeg;
 +				legPath = leg._path;
 +				legPath.style.strokeDashoffset = 0;
 +				//legPath.style.strokeOpacity = finalLegOpacity;
 +				leg.setStyle({opacity: finalLegOpacity});
  			}
  		}
 -		me.setOpacity(0.3);
 -
 -		//Set the opacity of the spiderLegs back to their correct value
 -		// The animations above override this until they complete.
 -		// If the initial opacity of the spiderlegs isn't 0 then they appear before the animation starts.
 -		this._group._forceLayout();
 -
 -		for (i = childMarkers.length - 1; i >= 0; i--) {
 -			m = childMarkers[i]._spiderLeg;
 -
 -			m.options.opacity = 0.5;
 -			m._path.setAttribute('stroke-opacity', 0.5);
 -		}
 +		this.setOpacity(0.3);
  
+ 		group._ignoreMove = false;
+ 
  		setTimeout(function () {
  			group._animationEnd();
  			group.fire('spiderfied');
@@@ -260,9 -277,9 +271,10 @@@
  			fg = group._featureGroup,
  			thisLayerPos = zoomDetails ? map._latLngToNewLayerPoint(this._latlng, zoomDetails.zoom, zoomDetails.center) : map.latLngToLayerPoint(this._latlng),
  			childMarkers = this.getAllChildMarkers(),
 -			m, i, a;
 +			svg = L.Path.SVG,
 +			m, i, leg, legPath, legLength;
  
+ 		group._ignoreMove = true;
  		group._animationStart();
  
  		//Make us visible and bring the child markers back in
diff --cc src/MarkerClusterGroup.js
index 32fe28c,209fff9..3c51026
--- a/src/MarkerClusterGroup.js
+++ b/src/MarkerClusterGroup.js
@@@ -163,9 -149,8 +163,11 @@@ L.MarkerClusterGroup = L.FeatureGroup.e
  		//Remove the marker from clusters
  		this._removeLayer(layer, true);
  
 +		// Refresh bounds and weighted positions.
 +		this._topClusterLevel._recalculateBounds();
 +
+ 		layer.off('move', this._childMarkerMoved, this);
+ 
  		if (this._featureGroup.hasLayer(layer)) {
  			this._featureGroup.removeLayer(layer);
  			if (layer.clusterShow) {
@@@ -574,23 -549,17 +577,33 @@@
  		}
  	},
  
 +	/**
 +	 * Removes a marker from all _gridUnclustered zoom levels, starting at the supplied zoom.
 +	 * @param marker to be removed from _gridUnclustered.
 +	 * @param z integer bottom start zoom level (included)
 +	 * @private
 +	 */
 +	_removeFromGridUnclustered: function (marker, z) {
- 		var map = this._map,
++		var map             = this._map,
 +		    gridUnclustered = this._gridUnclustered;
 +
 +		for (; z >= 0; z--) {
 +			if (!gridUnclustered[z].removeObject(marker, map.project(marker.getLatLng(), z))) {
 +				break;
 +			}
 +		}
 +	},
 +
+ 	_childMarkerMoved: function (e) {
+ 		if (!this._ignoreMove) {
+ 			e.target._latlng = e.oldLatLng;
+ 			this.removeLayer(e.target);
+ 
+ 			e.target._latlng = e.latlng;
+ 			this.addLayer(e.target);
+ 		}
 -		return;
+ 	},
+ 
  	//Internal function for removing a marker from everything.
  	//dontUpdateMap: set to true if you will handle updating the map manually (for bulk functions)
  	_removeLayer: function (marker, removeFromDistanceGrid, dontUpdateMap) {
@@@ -825,9 -803,18 +844,11 @@@
  		    markerPoint, z;
  
  		if (this.options.singleMarkerMode) {
 -			layer.options.icon = this.options.iconCreateFunction({
 -				getChildCount: function () {
 -					return 1;
 -				},
 -				getAllChildMarkers: function () {
 -					return [layer];
 -				}
 -			});
 +			this._overrideMarkerIcon(layer);
  		}
  
+ 		layer.on('move', this._childMarkerMoved, this);
+ 
  		//Find the lowest zoom level to slot this one in
  		for (; zoom >= 0; zoom--) {
  			markerPoint = this._map.project(layer.getLatLng(), zoom); // calculate pixel position
@@@ -966,167 -940,121 +988,171 @@@
  		} else {
  			newCluster._updateIcon();
  		}
 -	}
 -});
 -
 -L.MarkerClusterGroup.include(!L.DomUtil.TRANSITION ? {
 -
 -	//Non Animated versions of everything
 -	_animationStart: function () {
 -		//Do nothing...
  	},
 -	_animationZoomIn: function (previousZoomLevel, newZoomLevel) {
 -		this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, previousZoomLevel);
 -		this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds());
  
 -		//We didn't actually animate, but we use this event to mean "clustering animations have finished"
 -		this.fire('animationend');
 -	},
 -	_animationZoomOut: function (previousZoomLevel, newZoomLevel) {
 -		this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, previousZoomLevel);
 -		this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds());
 +	/**
 +	 * Implements the singleMarkerMode option.
 +	 * @param layer Marker to re-style using the Clusters iconCreateFunction.
 +	 * @returns {L.Icon} The newly created icon.
 +	 * @private
 +	 */
 +	_overrideMarkerIcon: function (layer) {
 +		var icon = layer.options.icon = this.options.iconCreateFunction({
 +			getChildCount: function () {
 +				return 1;
 +			},
 +			getAllChildMarkers: function () {
 +				return [layer];
 +			}
 +		});
  
 -		//We didn't actually animate, but we use this event to mean "clustering animations have finished"
 -		this.fire('animationend');
 -	},
 -	_animationAddLayer: function (layer, newCluster) {
 -		this._animationAddLayerNonAnimated(layer, newCluster);
 +		return icon;
  	}
 -} : {
 +});
  
 -	//Animated versions here
 -	_animationStart: function () {
 -		this._map._mapPane.className += ' leaflet-cluster-anim';
 -		this._inZoomAnimation++;
 -	},
 -	_animationEnd: function () {
 -		if (this._map) {
 -			this._map._mapPane.className = this._map._mapPane.className.replace(' leaflet-cluster-anim', '');
 +// Constant bounds used in case option "removeOutsideVisibleBounds" is set to false.
 +L.MarkerClusterGroup.include({
 +	_mapBoundsInfinite: new L.LatLngBounds(new L.LatLng(-Infinity, -Infinity), new L.LatLng(Infinity, Infinity))
 +});
 +
 +L.MarkerClusterGroup.include({
 +	_noAnimation: {
 +		//Non Animated versions of everything
 +		_animationStart: function () {
 +			//Do nothing...
 +		},
 +		_animationZoomIn: function (previousZoomLevel, newZoomLevel) {
 +			this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, previousZoomLevel);
 +			this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds());
 +
 +			//We didn't actually animate, but we use this event to mean "clustering animations have finished"
 +			this.fire('animationend');
 +		},
 +		_animationZoomOut: function (previousZoomLevel, newZoomLevel) {
 +			this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, previousZoomLevel);
 +			this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds());
 +
 +			//We didn't actually animate, but we use this event to mean "clustering animations have finished"
 +			this.fire('animationend');
 +		},
 +		_animationAddLayer: function (layer, newCluster) {
 +			this._animationAddLayerNonAnimated(layer, newCluster);
  		}
 -		this._inZoomAnimation--;
 -		this.fire('animationend');
  	},
 -	_animationZoomIn: function (previousZoomLevel, newZoomLevel) {
 -		var bounds = this._getExpandedVisibleBounds(),
 -		    fg = this._featureGroup,
 -		    i;
+ 
 -		this._ignoreMove = true;
 +	_withAnimation: {
 +		//Animated versions here
 +		_animationStart: function () {
 +			this._map._mapPane.className += ' leaflet-cluster-anim';
 +			this._inZoomAnimation++;
 +		},
 +		_animationZoomIn: function (previousZoomLevel, newZoomLevel) {
 +			var bounds = this._getExpandedVisibleBounds(),
 +			    fg     = this._featureGroup,
 +			    i;
  
 -		//Add all children of current clusters to map and remove those clusters from map
 -		this._topClusterLevel._recursively(bounds, previousZoomLevel, 0, function (c) {
 -			var startPos = c._latlng,
 -				markers = c._markers,
 -				m;
++			this._ignoreMove = true;
+ 
 -			if (!bounds.contains(startPos)) {
 -				startPos = null;
 -			}
 -
 -			if (c._isSingleParent() && previousZoomLevel + 1 === newZoomLevel) { //Immediately add the new child and remove us
 -				fg.removeLayer(c);
 -				c._recursivelyAddChildrenToMap(null, newZoomLevel, bounds);
 -			} else {
 -				//Fade out old cluster
 -				c.clusterHide();
 -				c._recursivelyAddChildrenToMap(startPos, newZoomLevel, bounds);
 -			}
 +			//Add all children of current clusters to map and remove those clusters from map
 +			this._topClusterLevel._recursively(bounds, previousZoomLevel, 0, function (c) {
 +				var startPos = c._latlng,
 +				    markers  = c._markers,
 +				    m;
  
 -			//Remove all markers that aren't visible any more
 -			//TODO: Do we actually need to do this on the higher levels too?
 -			for (i = markers.length - 1; i >= 0; i--) {
 -				m = markers[i];
 -				if (!bounds.contains(m._latlng)) {
 -					fg.removeLayer(m);
 +				if (!bounds.contains(startPos)) {
 +					startPos = null;
  				}
 -			}
  
 -		});
 +				if (c._isSingleParent() && previousZoomLevel + 1 === newZoomLevel) { //Immediately add the new child and remove us
 +					fg.removeLayer(c);
 +					c._recursivelyAddChildrenToMap(null, newZoomLevel, bounds);
 +				} else {
 +					//Fade out old cluster
 +					c.clusterHide();
 +					c._recursivelyAddChildrenToMap(startPos, newZoomLevel, bounds);
 +				}
  
 -		this._forceLayout();
 +				//Remove all markers that aren't visible any more
 +				//TODO: Do we actually need to do this on the higher levels too?
 +				for (i = markers.length - 1; i >= 0; i--) {
 +					m = markers[i];
 +					if (!bounds.contains(m._latlng)) {
 +						fg.removeLayer(m);
 +					}
 +				}
  
 -		//Update opacities
 -		this._topClusterLevel._recursivelyBecomeVisible(bounds, newZoomLevel);
 -		//TODO Maybe? Update markers in _recursivelyBecomeVisible
 -		fg.eachLayer(function (n) {
 -			if (!(n instanceof L.MarkerCluster) && n._icon) {
 -				n.clusterShow();
 -			}
 -		});
 +			});
  
 -		//update the positions of the just added clusters/markers
 -		this._topClusterLevel._recursively(bounds, previousZoomLevel, newZoomLevel, function (c) {
 -			c._recursivelyRestoreChildPositions(newZoomLevel);
 -		});
 +			this._forceLayout();
  
 -		this._ignoreMove = false;
 +			//Update opacities
 +			this._topClusterLevel._recursivelyBecomeVisible(bounds, newZoomLevel);
 +			//TODO Maybe? Update markers in _recursivelyBecomeVisible
 +			fg.eachLayer(function (n) {
 +				if (!(n instanceof L.MarkerCluster) && n._icon) {
 +					n.clusterShow();
 +				}
 +			});
++			this._ignoreMove = false;
  
 -		//Remove the old clusters and close the zoom animation
 -		this._enqueue(function () {
  			//update the positions of the just added clusters/markers
 -			this._topClusterLevel._recursively(bounds, previousZoomLevel, 0, function (c) {
 -				fg.removeLayer(c);
 -				c.clusterShow();
 +			this._topClusterLevel._recursively(bounds, previousZoomLevel, newZoomLevel, function (c) {
 +				c._recursivelyRestoreChildPositions(newZoomLevel);
  			});
  
 -			this._animationEnd();
 -		});
 -	},
 +			//Remove the old clusters and close the zoom animation
 +			this._enqueue(function () {
 +				//update the positions of the just added clusters/markers
 +				this._topClusterLevel._recursively(bounds, previousZoomLevel, 0, function (c) {
 +					fg.removeLayer(c);
 +					c.clusterShow();
 +				});
 +
 +				this._animationEnd();
 +			});
 +		},
  
 -	_animationZoomOut: function (previousZoomLevel, newZoomLevel) {
 -		this._animationZoomOutSingle(this._topClusterLevel, previousZoomLevel - 1, newZoomLevel);
 +		_animationZoomOut: function (previousZoomLevel, newZoomLevel) {
 +			this._animationZoomOutSingle(this._topClusterLevel, previousZoomLevel - 1, newZoomLevel);
  
 -		//Need to add markers for those that weren't on the map before but are now
 -		this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds());
 -		//Remove markers that were on the map before but won't be now
 -		this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, previousZoomLevel, this._getExpandedVisibleBounds());
 +			//Need to add markers for those that weren't on the map before but are now
 +			this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds());
 +			//Remove markers that were on the map before but won't be now
 +			this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, previousZoomLevel, this._getExpandedVisibleBounds());
 +		},
 +		_animationAddLayer: function (layer, newCluster) {
 +			var me = this,
 +			    fg = this._featureGroup;
 +
 +			fg.addLayer(layer);
 +			if (newCluster !== layer) {
 +				if (newCluster._childCount > 2) { //Was already a cluster
 +
 +					newCluster._updateIcon();
 +					this._forceLayout();
 +					this._animationStart();
 +
 +					layer._setPos(this._map.latLngToLayerPoint(newCluster.getLatLng()));
 +					layer.clusterHide();
 +
 +					this._enqueue(function () {
 +						fg.removeLayer(layer);
 +						layer.clusterShow();
 +
 +						me._animationEnd();
 +					});
 +
 +				} else { //Just became a cluster
 +					this._forceLayout();
 +
 +					me._animationStart();
 +					me._animationZoomOutSingle(newCluster, this._map.getMaxZoom(), this._map.getZoom());
 +				}
 +			}
 +		}
  	},
 +
 +	// Private methods for animated versions.
  	_animationZoomOutSingle: function (cluster, previousZoomLevel, newZoomLevel) {
  		var bounds = this._getExpandedVisibleBounds();
  

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/leaflet-markercluster.git



More information about the Pkg-javascript-commits mailing list