From 2099aefdcaf7ecc5e317e8d323085c2d3cc75931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20S=C3=A1nchez=20Ortega?= Date: Tue, 10 Feb 2015 15:46:01 +0100 Subject: [PATCH 1/4] On becoming visible, markers retain their original opacity. Fixes Leaflet/Leaflet.markercluster#312 --- build/deps.js | 1 + src/MarkerCluster.Spiderfier.js | 2 +- src/MarkerCluster.js | 24 ++++++++++++------------ src/MarkerClusterGroup.js | 22 +++++++++++----------- src/MarkerOpacity.js | 26 ++++++++++++++++++++++++++ 5 files changed, 51 insertions(+), 24 deletions(-) create mode 100644 src/MarkerOpacity.js diff --git a/build/deps.js b/build/deps.js index 6a466ea35..40b8b203f 100644 --- a/build/deps.js +++ b/build/deps.js @@ -3,6 +3,7 @@ var deps = { Core: { src: ['MarkerClusterGroup.js', 'MarkerCluster.js', + 'MarkerOpacity.js', 'DistanceGrid.js'], desc: 'The core of the library.' }, diff --git a/src/MarkerCluster.Spiderfier.js b/src/MarkerCluster.Spiderfier.js index ead03b4ce..26799038c 100644 --- a/src/MarkerCluster.Spiderfier.js +++ b/src/MarkerCluster.Spiderfier.js @@ -196,7 +196,7 @@ L.MarkerCluster.include(!L.DomUtil.TRANSITION ? { m.setLatLng(newPos); if (m.setOpacity) { - m.setOpacity(1); + m.clusterShow(); } diff --git a/src/MarkerCluster.js b/src/MarkerCluster.js index cdca102ef..2ce3190c7 100644 --- a/src/MarkerCluster.js +++ b/src/MarkerCluster.js @@ -169,7 +169,7 @@ L.MarkerCluster = L.Marker.extend({ //Only do it if the icon is still on the map if (m._icon) { m._setPos(center); - m.setOpacity(0); + m.clusterHide(); } } }, @@ -180,7 +180,7 @@ L.MarkerCluster = L.Marker.extend({ cm = childClusters[j]; if (cm._icon) { cm._setPos(center); - cm.setOpacity(0); + cm.clusterHide(); } } } @@ -195,10 +195,10 @@ L.MarkerCluster = L.Marker.extend({ //TODO: depthToAnimateIn affects _isSingleParent, if there is a multizoom we may/may not be. //As a hack we only do a animation free zoom on a single level zoom, if someone does multiple levels then we always animate if (c._isSingleParent() && previousZoomLevel - 1 === newZoomLevel) { - c.setOpacity(1); + c.clusterShow(); c._recursivelyRemoveChildrenFromMap(bounds, previousZoomLevel); //Immediately remove our children as we are replacing them. TODO previousBounds not bounds } else { - c.setOpacity(0); + c.clusterHide(); } c._addToMap(); @@ -208,7 +208,7 @@ L.MarkerCluster = L.Marker.extend({ _recursivelyBecomeVisible: function (bounds, zoomLevel) { this._recursively(bounds, 0, zoomLevel, null, function (c) { - c.setOpacity(1); + c.clusterShow(); }); }, @@ -231,8 +231,8 @@ L.MarkerCluster = L.Marker.extend({ nm._backupLatlng = nm.getLatLng(); nm.setLatLng(startPos); - if (nm.setOpacity) { - nm.setOpacity(0); + if (nm.clusterHide) { + nm.clusterHide(); } } @@ -284,8 +284,8 @@ L.MarkerCluster = L.Marker.extend({ m = c._markers[i]; if (!exceptBounds || !exceptBounds.contains(m._latlng)) { c._group._featureGroup.removeLayer(m); - if (m.setOpacity) { - m.setOpacity(1); + if (m.clusterShow) { + m.clusterShow(); } } } @@ -296,8 +296,8 @@ L.MarkerCluster = L.Marker.extend({ m = c._childClusters[i]; if (!exceptBounds || !exceptBounds.contains(m._latlng)) { c._group._featureGroup.removeLayer(m); - if (m.setOpacity) { - m.setOpacity(1); + if (m.clusterShow) { + m.clusterShow(); } } } @@ -314,7 +314,7 @@ L.MarkerCluster = L.Marker.extend({ _recursively: function (boundsToApplyTo, zoomLevelToStart, zoomLevelToStop, runAtEveryLevel, runAtBottomLevel) { var childClusters = this._childClusters, zoom = this._zoom, - i, c; + i, c; if (zoomLevelToStart > zoom) { //Still going down to required depth, just recurse to child clusters for (i = childClusters.length - 1; i >= 0; i--) { diff --git a/src/MarkerClusterGroup.js b/src/MarkerClusterGroup.js index c487468b1..f88335b30 100644 --- a/src/MarkerClusterGroup.js +++ b/src/MarkerClusterGroup.js @@ -148,8 +148,8 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ if (this._featureGroup.hasLayer(layer)) { this._featureGroup.removeLayer(layer); - if (layer.setOpacity) { - layer.setOpacity(1); + if (layer.clusterShow) { + layer.clusterShow(); } } @@ -276,8 +276,8 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ if (fg.hasLayer(m)) { fg.removeLayer(m); - if (m.setOpacity) { - m.setOpacity(1); + if (m.clusterShow) { + m.clusterShow(); } } } @@ -967,7 +967,7 @@ L.MarkerClusterGroup.include(!L.DomUtil.TRANSITION ? { c._recursivelyAddChildrenToMap(null, newZoomLevel, bounds); } else { //Fade out old cluster - c.setOpacity(0); + c.clusterHide(); c._recursivelyAddChildrenToMap(startPos, newZoomLevel, bounds); } @@ -989,7 +989,7 @@ L.MarkerClusterGroup.include(!L.DomUtil.TRANSITION ? { //TODO Maybe? Update markers in _recursivelyBecomeVisible fg.eachLayer(function (n) { if (!(n instanceof L.MarkerCluster) && n._icon) { - n.setOpacity(1); + n.clusterShow(); } }); @@ -1003,7 +1003,7 @@ L.MarkerClusterGroup.include(!L.DomUtil.TRANSITION ? { //update the positions of the just added clusters/markers this._topClusterLevel._recursively(bounds, previousZoomLevel, 0, function (c) { fg.removeLayer(c); - c.setOpacity(1); + c.clusterShow(); }); this._animationEnd(); @@ -1039,8 +1039,8 @@ L.MarkerClusterGroup.include(!L.DomUtil.TRANSITION ? { var m = cluster._markers[0]; //If we were in a cluster animation at the time then the opacity and position of our child could be wrong now, so fix it m.setLatLng(m.getLatLng()); - if (m.setOpacity) { - m.setOpacity(1); + if (m.clusterShow) { + m.clusterShow(); } } else { cluster._recursively(bounds, newZoomLevel, 0, function (c) { @@ -1063,11 +1063,11 @@ L.MarkerClusterGroup.include(!L.DomUtil.TRANSITION ? { this._animationStart(); layer._setPos(this._map.latLngToLayerPoint(newCluster.getLatLng())); - layer.setOpacity(0); + layer.clusterHide(); this._enqueue(function () { fg.removeLayer(layer); - layer.setOpacity(1); + layer.clusterShow(); me._animationEnd(); }); diff --git a/src/MarkerOpacity.js b/src/MarkerOpacity.js new file mode 100644 index 000000000..f1df08c62 --- /dev/null +++ b/src/MarkerOpacity.js @@ -0,0 +1,26 @@ + +/* + * Extends L.Marker to include two extra methods: clusterHide and clusterShow. + * + * They work as setOpacity(0) and setOpacity(1) respectively, but + * they will remember the marker's opacity when hiding and showing it again. + * + */ + + +L.Marker.include({ + + clusterHide: function(){ + this.options.opacityWhenUnclustered = this.options.opacity || 1; + return this.setOpacity(0); + }, + + clusterShow: function(){ + var ret = this.setOpacity(this.options.opacity || this.options.opacityWhenUnclustered); + delete this.options.opacityWhenUnclustered; + return ret; + } + +}); + + From 477a0e47d2adbd01265820cd0cbc7d50eb7ae232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20S=C3=A1nchez=20Ortega?= Date: Tue, 10 Feb 2015 15:51:20 +0100 Subject: [PATCH 2/4] Fix indentation to make Jake and TravisCI happy. --- src/MarkerOpacity.js | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/MarkerOpacity.js b/src/MarkerOpacity.js index f1df08c62..beaef098b 100644 --- a/src/MarkerOpacity.js +++ b/src/MarkerOpacity.js @@ -1,26 +1,26 @@ /* - * Extends L.Marker to include two extra methods: clusterHide and clusterShow. - * - * They work as setOpacity(0) and setOpacity(1) respectively, but - * they will remember the marker's opacity when hiding and showing it again. - * - */ +* Extends L.Marker to include two extra methods: clusterHide and clusterShow. +* +* They work as setOpacity(0) and setOpacity(1) respectively, but +* they will remember the marker's opacity when hiding and showing it again. +* +*/ L.Marker.include({ - - clusterHide: function(){ - this.options.opacityWhenUnclustered = this.options.opacity || 1; - return this.setOpacity(0); - }, - - clusterShow: function(){ - var ret = this.setOpacity(this.options.opacity || this.options.opacityWhenUnclustered); - delete this.options.opacityWhenUnclustered; - return ret; - } - + + clusterHide: function () { + this.options.opacityWhenUnclustered = this.options.opacity || 1; + return this.setOpacity(0); + }, + + clusterShow: function () { + var ret = this.setOpacity(this.options.opacity || this.options.opacityWhenUnclustered); + delete this.options.opacityWhenUnclustered; + return ret; + } + }); From 773d500271492d50ccb93081b3fd14fd8d55a911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20S=C3=A1nchez=20Ortega?= Date: Wed, 11 Feb 2015 16:00:43 +0100 Subject: [PATCH 3/4] Have spiderifier use the opacity-retaining functionality. --- src/MarkerCluster.Spiderfier.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MarkerCluster.Spiderfier.js b/src/MarkerCluster.Spiderfier.js index 26799038c..c2b3fdc9f 100644 --- a/src/MarkerCluster.Spiderfier.js +++ b/src/MarkerCluster.Spiderfier.js @@ -169,7 +169,7 @@ L.MarkerCluster.include(!L.DomUtil.TRANSITION ? { //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.setOpacity(0); + m.clusterHide(); fg.addLayer(m); @@ -287,7 +287,7 @@ L.MarkerCluster.include(!L.DomUtil.TRANSITION ? { //Hack override the location to be our center if (m.setOpacity) { m._setPos(thisLayerPos); - m.setOpacity(0); + m.clusterHide(); } else { fg.removeLayer(m); } @@ -329,7 +329,7 @@ L.MarkerCluster.include(!L.DomUtil.TRANSITION ? { if (m.setOpacity) { - m.setOpacity(1); + m.clusterShow(); m.setZIndexOffset(0); } From 13c6aff4b635b22fab2a9448cd3f54539cf7b8ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20S=C3=A1nchez=20Ortega?= Date: Thu, 26 Mar 2015 11:30:01 +0100 Subject: [PATCH 4/4] Unit tests for the "remember opacity" functionality --- spec/index.html | 3 + spec/suites/RememberOpacity.js | 151 +++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 spec/suites/RememberOpacity.js diff --git a/spec/index.html b/spec/index.html index a68feeefe..ad1549cf1 100644 --- a/spec/index.html +++ b/spec/index.html @@ -19,6 +19,7 @@ + + + diff --git a/spec/suites/RememberOpacity.js b/spec/suites/RememberOpacity.js new file mode 100644 index 000000000..bb023a59f --- /dev/null +++ b/spec/suites/RememberOpacity.js @@ -0,0 +1,151 @@ +describe('Remember opacity', function () { + var map, div, clock, markers; + + var markerDefs = [ + {latLng: [ 0, 0], opts: {opacity: 0.9}}, + {latLng: [ 0, 1], opts: {opacity: 0.5}}, + {latLng: [ 0,-1], opts: {opacity: 0.5}}, + {latLng: [ 1, 0], opts: {opacity: 0.5}}, + {latLng: [-1, 0], opts: {opacity: 0.5}}, + {latLng: [ 1, 1], opts: {opacity: 0.2}}, + {latLng: [ 1,-1], opts: {opacity: 0.2}}, + {latLng: [-1, 1], opts: {opacity: 0.2}}, + {latLng: [-1,-1], opts: {opacity: 0.2}} + ]; + + var bounds = L.latLngBounds( L.latLng( -1.1, -1.1), + L.latLng( 1.1, 1.1) ); + + beforeEach(function () { + clock = sinon.useFakeTimers(); + + div = document.createElement('div'); + div.style.width = '200px'; + div.style.height = '200px'; + document.body.appendChild(div); + + map = L.map(div, { maxZoom: 18 }); + + markers = []; + for (var i=0; i