[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