diff --git a/demo/index.html b/demo/index.html index 77fd9cb..51102dd 100644 --- a/demo/index.html +++ b/demo/index.html @@ -2,18 +2,22 @@ maptalks.markercluster demo - - + + + - @@ -51,22 +55,18 @@ 'forceRenderOnZooming' : true, 'maxClusterZoom' : 16, //"count" is an internal variable: marker count in the cluster. - 'symbol' :{ - 'markerType' : 'ellipse', - 'markerFill' : { property:'count', type:'interval', stops: [[0, 'rgb(135, 196, 240)'], [9, 'rgba(222, 125, 44, 1)'], [99, 'rgb(156, 38, 50)']] }, - 'markerFillOpacity' : 1, - 'markerLineOpacity' : 1, - 'markerLineWidth' : 3, - 'markerLineColor' : '#fff', - 'markerWidth' : { property:'count', type:'interval', stops: [[0, 40], [9, 60], [99, 80]] }, - 'markerHeight' : { property:'count', type:'interval', stops: [[0, 40], [9, 60], [99, 80]] } + 'symbol': { + 'markerType': 'ellipse', + 'markerFill': { property: 'count', type: 'interval', stops: [[0, '#00F5FF'], [9, '#98FB98'], [99, '#EEEE00'], [300, '#FF6EB4']] }, + 'markerFillOpacity': 0.9, + 'markerLineOpacity': 0.3, + 'markerLineWidth': 10, + 'markerLineColor': { property: 'count', type: 'interval', stops: [[0, '#00F5FF'], [9, '#98FB98'], [99, '#EEEE00'], [300, '#FF6EB4']] }, + 'markerWidth': { property: 'count', type: 'interval', stops: [[0, 25], [9, 30], [99, 35], [500, 40]] }, + 'markerHeight': { property: 'count', type: 'interval', stops: [[0, 25], [9, 30], [99, 35], [500, 40]] } }, - 'textSymbol' : { - 'textFaceName' : 'monospace', - 'textSize' : 20, - 'textFill' : '#fff' - }, - 'drawClusterText' : true + 'drawClusterText': true, + 'single': true }); map.addLayer(clusterLayer); diff --git a/dist/maptalks.markercluster.js b/dist/maptalks.markercluster.js index a427e8c..cd3dd4e 100644 --- a/dist/maptalks.markercluster.js +++ b/dist/maptalks.markercluster.js @@ -28,7 +28,8 @@ var options = { 'textSymbol': null, 'animation': true, 'animationDuration': 450, - 'maxClusterZoom': null + 'maxClusterZoom': null, + 'single': true }; var ClusterLayer = function (_maptalks$VectorLayer) { @@ -114,6 +115,19 @@ var ClusterLayer = function (_maptalks$VectorLayer) { json['type'] = 'ClusterLayer'; return json; }; + /** + * Get the ClusterLayer's current clusters + * @return {Object} layer's clusters + **/ + + + ClusterLayer.prototype.getClusters = function getClusters() { + var renderer$$1 = this._getRenderer(); + if (renderer$$1) { + return renderer$$1._currentClusters || []; + } + return []; + }; return ClusterLayer; }(maptalks.VectorLayer); @@ -126,7 +140,7 @@ ClusterLayer.registerJSONType('ClusterLayer'); var defaultTextSymbol = { 'textFaceName': '"microsoft yahei"', - 'textSize': 16, + 'textSize': 12, 'textDx': 0, 'textDy': 0 }; @@ -200,7 +214,7 @@ ClusterLayer.registerRenderer('canvas', function (_maptalks$renderer$Ve) { font = void 0; for (var p in zoomClusters) { this._currentGrid = zoomClusters[p]; - if (zoomClusters[p]['count'] === 1) { + if (zoomClusters[p]['count'] === 1 && this.layer.options['single']) { var marker = zoomClusters[p]['children'][0]; marker._cluster = zoomClusters[p]; this._markersToDraw.push(marker); @@ -307,11 +321,20 @@ ClusterLayer.registerRenderer('canvas', function (_maptalks$renderer$Ve) { _class.prototype._drawLayer = function _drawLayer(clusters) { var _this4 = this; - this._currentClusters = clusters; + //this._currentClusters = clusters; + this._currentClusters = this.layer._currentClusters = clusters; delete this._clusterMaskExtent; var layer = this.layer; - if (layer.options['animation'] && this._animated && this._inout === 'out') { - this._player = maptalks.animation.Animation.animate({ 'd': [0, 1] }, { 'speed': layer.options['animationDuration'], 'easing': 'inAndOut' }, function (frame) { + var dr = [0, 1]; + //if (layer.options['animation'] && this._animated && this._inout === 'out') { + if (layer.options['animation'] && this._animated && this._inout) { + if (this._inout === 'in') { + dr = [1, 0]; + clusters = this._zoomInClusters; + } else if (this._inout === 'out') { + dr = [0, 1]; + } + this._player = maptalks.animation.Animation.animate({ 'd': dr }, { 'speed': layer.options['animationDuration'], 'easing': 'inAndOut' }, function (frame) { if (frame.state.playState === 'finished') { _this4._animated = false; _this4._drawMarkers(); @@ -321,7 +344,7 @@ ClusterLayer.registerRenderer('canvas', function (_maptalks$renderer$Ve) { _this4.setCanvasUpdated(); } }).play(); - this._drawClusters(clusters, 0); + this._drawClusters(clusters, dr[0]); this.setCanvasUpdated(); } else { this._animated = false; @@ -582,8 +605,19 @@ ClusterLayer.registerRenderer('canvas', function (_maptalks$renderer$Ve) { }; _class.prototype.onZoomEnd = function onZoomEnd() { + var zoom = this.getMap().getZoom(); this._animated = true; this._computeGrid(); + if (this._inout === 'in') { + if (!this._clusterCache[zoom + 1]) { + this._clusterCache[zoom + 1] = this._computeZoomGrid(zoom + 1); + } + var tempCluster = this._clusterCache[zoom + 1].clusters; + this._zoomInClusters = []; + for (var p in tempCluster) { + this._zoomInClusters.push(tempCluster[p]); + } + } _maptalks$renderer$Ve.prototype.onZoomEnd.apply(this, arguments); }; diff --git a/dist/maptalks.markercluster.min.js b/dist/maptalks.markercluster.min.js index ed07a45..8e1a2b3 100644 --- a/dist/maptalks.markercluster.min.js +++ b/dist/maptalks.markercluster.min.js @@ -6,4 +6,4 @@ /*! * requires maptalks@^0.25.0 */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("maptalks")):"function"==typeof define&&define.amd?define(["exports","maptalks"],e):e(t.maptalks=t.maptalks||{},t.maptalks)}(this,function(t,e){"use strict";function r(t,e){for(var r=Object.getOwnPropertyNames(e),o=0;oi)return delete this._currentClusters,this._markersToDraw=this.layer._geoList,void t.prototype.draw.apply(this,arguments);this._clusterNeedRedraw&&(this._clearDataCache(),this._computeGrid(),this._clusterNeedRedraw=!1);var n=this._clusterCache[o]?this._clusterCache[o].clusters:null;this._markersToDraw=[];var s=r.getContainerExtent(),a=[],p=void 0,l=void 0,u=void 0,c=void 0,h=void 0,y=void 0;for(var d in n)if(this._currentGrid=n[d],1!==n[d].count)u=this._getSprite(),c=u.canvas.width,h=u.canvas.height,p=r._prjToContainerPoint(n[d].center),l=new e.PointExtent(p.sub(c,h),p.add(c,h)),s.intersects(l)&&(y=e.StringUtil.getFont(this._textSymbol),n[d].textSize||(n[d].textSize=e.StringUtil.stringLength(n[d].count,y).toPoint()._multi(.5)),a.push(n[d]));else{var m=n[d].children[0];m._cluster=n[d],this._markersToDraw.push(m)}this._drawLayer(a)},r.prototype.drawOnInteracting=function(){this._currentClusters&&this._drawClusters(this._currentClusters,1),t.prototype.drawOnInteracting.apply(this,arguments)},r.prototype.forEachGeo=function(t,e){this._markersToDraw&&this._markersToDraw.forEach(function(r){e?t.call(e,r):t(r)})},r.prototype.onGeometryAdd=function(){this._clusterNeedRedraw=!0,t.prototype.onGeometryAdd.apply(this,arguments)},r.prototype.onGeometryRemove=function(){this._clusterNeedRedraw=!0,t.prototype.onGeometryRemove.apply(this,arguments)},r.prototype.onGeometryPositionChange=function(){this._clusterNeedRedraw=!0,t.prototype.onGeometryPositionChange.apply(this,arguments)},r.prototype.onRemove=function(){this._clearDataCache()},r.prototype.identify=function(t){var e=this.getMap();if(t=e.coordinateToContainerPoint(t),!this._currentClusters)return null;for(var r=this._currentGrid,o=0;o.5?1:e)})},r.prototype._drawCluster=function(t,r,o){this._currentGrid=r;var i=this.context,n=this._getSprite(),s=i.globalAlpha;if(s*o!==0){if(i.globalAlpha=s*o,n){var a=t.add(n.offset)._sub(n.canvas.width/2,n.canvas.height/2);i.drawImage(n.canvas,a.x,a.y)}if(this.layer.options.drawClusterText&&r.textSize){e.Canvas.prepareCanvasFont(i,this._textSymbol);var p=this._textSymbol.textDx||0,l=this._textSymbol.textDy||0;e.Canvas.fillText(i,r.count,t.sub(r.textSize).add(p,l))}i.globalAlpha=s}},r.prototype._getSprite=function(){this._spriteCache||(this._spriteCache={});var t=e.Util.getSymbolStamp(this._symbol);return this._spriteCache[t]||(this._spriteCache[t]=new e.Marker([0,0],{symbol:this._symbol})._getSprite(this.resources,this.getMap().CanvasClass)),this._spriteCache[t]},r.prototype._initGridSystem=function(){var t=[],e=void 0,r=void 0;this.layer.forEach(function(o){r=o._getPrjCoordinates(),e=e?e._combine(o._getPrjExtent()):o._getPrjExtent(),t.push({x:r.x,y:r.y,id:o._getInternalId(),geometry:o})}),this._markerExtent=e,this._markerPoints=t},r.prototype._computeGrid=function(){var t=this.getMap(),e=t.getZoom();this._markerExtent||this._initGridSystem(),this._clusterCache||(this._clusterCache={});var r=t._getResolution(t.getMinZoom())>t._getResolution(t.getMaxZoom())?e-1:e+1;this._clusterCache[r]&&this._clusterCache[r].length===this.layer.getCount()&&(this._clusterCache[e]=this._clusterCache[r]),this._clusterCache[e]||(this._clusterCache[e]=this._computeZoomGrid(e))},r.prototype._computeZoomGrid=function(t){if(!this._markerExtent)return null;var r=this.getMap(),o=r._getResolution(t)*this.layer.options.maxClusterRadius,i=r._getResolution(t-1)?r._getResolution(t-1)*this.layer.options.maxClusterRadius:null,n=this._clusterCache[t-1];!n&&t-1>=r.getMinZoom()&&(this._clusterCache[t-1]=n=this._computeZoomGrid(t-1));for(var s=this._markerPoints,a={},p=this._markerExtent.getMin(),l=void 0,u=void 0,c=void 0,h=void 0,y=void 0,d=void 0,m=0,_=s.length;m<_;m++)l=Math.floor((s[m].x-p.x)/o),u=Math.floor((s[m].y-p.y)/o),c=l+"_"+u,a[c]?(a[c].sum._add(new e.Coordinate(s[m].x,s[m].y)),a[c].count++,a[c].center=a[c].sum.multi(1/a[c].count),a[c].children.push(s[m].geometry)):(a[c]={sum:new e.Coordinate(s[m].x,s[m].y),center:new e.Coordinate(s[m].x,s[m].y),count:1,children:[s[m].geometry],key:c+""},i&&n&&(h=Math.floor((s[m].x-p.x)/i),y=Math.floor((s[m].y-p.y)/i),d=h+"_"+y,a[c].parent=n.clusterMap[d]));return this._mergeClusters(a,o/2)},r.prototype._mergeClusters=function(t,e){var r={};for(var o in t)r[o]=t[o];var i={},n={},s=void 0,a=void 0;for(var p in t)if(s=t[p],!n[s.key])for(var l=s.key.split("_"),u=+l[0],c=+l[1],h=-1;h<=1;h++)for(var y=-1;y<=1;y++)if(0!==h||0!==y){var d=u+h+"_"+(c+y);a=t[d],a&&this._distanceTo(s.center,a.center)<=e&&(i[s.key]||(i[s.key]=[]),i[s.key].push(a),n[a.key]=1)}for(var m in i){var _=t[m];if(_){for(var f=i[m],v=0;ve.to?"in":"out",this._stopAnim(),t.prototype.onZoomStart.call(this,e)},r.prototype.onZoomEnd=function(){this._animated=!0,this._computeGrid(),t.prototype.onZoomEnd.apply(this,arguments)},r.prototype._clearDataCache=function(){this._stopAnim(),delete this._markerExtent,delete this._markerPoints,delete this._clusterCache},r}(e.renderer.VectorLayerCanvasRenderer)),t.ClusterLayer=a,Object.defineProperty(t,"__esModule",{value:!0}),"undefined"!=typeof console&&console.log("maptalks.markercluster v0.5.0, requires maptalks@^0.25.0.")}); \ No newline at end of file +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("maptalks")):"function"==typeof define&&define.amd?define(["exports","maptalks"],e):e(t.maptalks=t.maptalks||{},t.maptalks)}(this,function(t,e){"use strict";function r(t,e){for(var r=Object.getOwnPropertyNames(e),o=0;oi)return delete this._currentClusters,this._markersToDraw=this.layer._geoList,void t.prototype.draw.apply(this,arguments);this._clusterNeedRedraw&&(this._clearDataCache(),this._computeGrid(),this._clusterNeedRedraw=!1);var n=this._clusterCache[o]?this._clusterCache[o].clusters:null;this._markersToDraw=[];var s=r.getContainerExtent(),a=[],l=void 0,u=void 0,p=void 0,c=void 0,h=void 0,y=void 0;for(var d in n)if(this._currentGrid=n[d],1===n[d].count&&this.layer.options.single){var _=n[d].children[0];_._cluster=n[d],this._markersToDraw.push(_)}else p=this._getSprite(),c=p.canvas.width,h=p.canvas.height,l=r._prjToContainerPoint(n[d].center),u=new e.PointExtent(l.sub(c,h),l.add(c,h)),s.intersects(u)&&(y=e.StringUtil.getFont(this._textSymbol),n[d].textSize||(n[d].textSize=e.StringUtil.stringLength(n[d].count,y).toPoint()._multi(.5)),a.push(n[d]));this._drawLayer(a)},r.prototype.drawOnInteracting=function(){this._currentClusters&&this._drawClusters(this._currentClusters,1),t.prototype.drawOnInteracting.apply(this,arguments)},r.prototype.forEachGeo=function(t,e){this._markersToDraw&&this._markersToDraw.forEach(function(r){e?t.call(e,r):t(r)})},r.prototype.onGeometryAdd=function(){this._clusterNeedRedraw=!0,t.prototype.onGeometryAdd.apply(this,arguments)},r.prototype.onGeometryRemove=function(){this._clusterNeedRedraw=!0,t.prototype.onGeometryRemove.apply(this,arguments)},r.prototype.onGeometryPositionChange=function(){this._clusterNeedRedraw=!0,t.prototype.onGeometryPositionChange.apply(this,arguments)},r.prototype.onRemove=function(){this._clearDataCache()},r.prototype.identify=function(t){var e=this.getMap();if(t=e.coordinateToContainerPoint(t),!this._currentClusters)return null;for(var r=this._currentGrid,o=0;o.5?1:e)})},r.prototype._drawCluster=function(t,r,o){this._currentGrid=r;var i=this.context,n=this._getSprite(),s=i.globalAlpha;if(s*o!=0){if(i.globalAlpha=s*o,n){var a=t.add(n.offset)._sub(n.canvas.width/2,n.canvas.height/2);i.drawImage(n.canvas,a.x,a.y)}if(this.layer.options.drawClusterText&&r.textSize){e.Canvas.prepareCanvasFont(i,this._textSymbol);var l=this._textSymbol.textDx||0,u=this._textSymbol.textDy||0;e.Canvas.fillText(i,r.count,t.sub(r.textSize).add(l,u))}i.globalAlpha=s}},r.prototype._getSprite=function(){this._spriteCache||(this._spriteCache={});var t=e.Util.getSymbolStamp(this._symbol);return this._spriteCache[t]||(this._spriteCache[t]=new e.Marker([0,0],{symbol:this._symbol})._getSprite(this.resources,this.getMap().CanvasClass)),this._spriteCache[t]},r.prototype._initGridSystem=function(){var t=[],e=void 0,r=void 0;this.layer.forEach(function(o){r=o._getPrjCoordinates(),e=e?e._combine(o._getPrjExtent()):o._getPrjExtent(),t.push({x:r.x,y:r.y,id:o._getInternalId(),geometry:o})}),this._markerExtent=e,this._markerPoints=t},r.prototype._computeGrid=function(){var t=this.getMap(),e=t.getZoom();this._markerExtent||this._initGridSystem(),this._clusterCache||(this._clusterCache={});var r=t._getResolution(t.getMinZoom())>t._getResolution(t.getMaxZoom())?e-1:e+1;this._clusterCache[r]&&this._clusterCache[r].length===this.layer.getCount()&&(this._clusterCache[e]=this._clusterCache[r]),this._clusterCache[e]||(this._clusterCache[e]=this._computeZoomGrid(e))},r.prototype._computeZoomGrid=function(t){if(!this._markerExtent)return null;var r=this.getMap(),o=r._getResolution(t)*this.layer.options.maxClusterRadius,i=r._getResolution(t-1)?r._getResolution(t-1)*this.layer.options.maxClusterRadius:null,n=this._clusterCache[t-1];!n&&t-1>=r.getMinZoom()&&(this._clusterCache[t-1]=n=this._computeZoomGrid(t-1));for(var s=this._markerPoints,a={},l=this._markerExtent.getMin(),u=void 0,p=void 0,c=void 0,h=void 0,y=void 0,d=void 0,_=0,m=s.length;_e.to?"in":"out",this._stopAnim(),t.prototype.onZoomStart.call(this,e)},r.prototype.onZoomEnd=function(){var e=this.getMap().getZoom();if(this._animated=!0,this._computeGrid(),"in"===this._inout){this._clusterCache[e+1]||(this._clusterCache[e+1]=this._computeZoomGrid(e+1));var r=this._clusterCache[e+1].clusters;this._zoomInClusters=[];for(var o in r)this._zoomInClusters.push(r[o])}t.prototype.onZoomEnd.apply(this,arguments)},r.prototype._clearDataCache=function(){this._stopAnim(),delete this._markerExtent,delete this._markerPoints,delete this._clusterCache},r}(e.renderer.VectorLayerCanvasRenderer)),t.ClusterLayer=a,Object.defineProperty(t,"__esModule",{value:!0}),"undefined"!=typeof console&&console.log("maptalks.markercluster v0.5.0, requires maptalks@^0.25.0.")}); \ No newline at end of file diff --git a/index.js b/index.js index 93be4fe..16a15c5 100644 --- a/index.js +++ b/index.js @@ -8,7 +8,8 @@ const options = { 'textSymbol' : null, 'animation' : true, 'animationDuration' : 450, - 'maxClusterZoom' : null + 'maxClusterZoom' : null, + 'single':true }; export class ClusterLayer extends maptalks.VectorLayer { @@ -84,6 +85,17 @@ export class ClusterLayer extends maptalks.VectorLayer { json['type'] = 'ClusterLayer'; return json; } + /** + * Get the ClusterLayer's current clusters + * @return {Object} layer's clusters + **/ + getClusters() { + const renderer = this._getRenderer(); + if (renderer) { + return renderer._currentClusters || []; + } + return []; + } } // merge to define ClusterLayer's default options. @@ -94,7 +106,7 @@ ClusterLayer.registerJSONType('ClusterLayer'); const defaultTextSymbol = { 'textFaceName' : '"microsoft yahei"', - 'textSize' : 16, + 'textSize' : 12, 'textDx' : 0, 'textDy' : 0 }; @@ -158,7 +170,7 @@ ClusterLayer.registerRenderer('canvas', class extends maptalks.renderer.VectorLa let pt, pExt, sprite, width, height, font; for (const p in zoomClusters) { this._currentGrid = zoomClusters[p]; - if (zoomClusters[p]['count'] === 1) { + if (zoomClusters[p]['count'] === 1 && this.layer.options['single']) { const marker = zoomClusters[p]['children'][0]; marker._cluster = zoomClusters[p]; this._markersToDraw.push(marker); @@ -259,12 +271,21 @@ ClusterLayer.registerRenderer('canvas', class extends maptalks.renderer.VectorLa } _drawLayer(clusters) { - this._currentClusters = clusters; + //this._currentClusters = clusters; + this._currentClusters = this.layer._currentClusters = clusters; delete this._clusterMaskExtent; const layer = this.layer; - if (layer.options['animation'] && this._animated && this._inout === 'out') { + let dr = [0, 1]; + //if (layer.options['animation'] && this._animated && this._inout === 'out') { + if (layer.options['animation'] && this._animated && this._inout) { + if (this._inout === 'in') { + dr = [1, 0]; + clusters = this._zoomInClusters; + } else if (this._inout === 'out') { + dr = [0, 1]; + } this._player = maptalks.animation.Animation.animate( - { 'd' : [0, 1] }, + { 'd' : dr }, { 'speed' : layer.options['animationDuration'], 'easing' : 'inAndOut' }, frame => { if (frame.state.playState === 'finished') { @@ -278,7 +299,7 @@ ClusterLayer.registerRenderer('canvas', class extends maptalks.renderer.VectorLa } ) .play(); - this._drawClusters(clusters, 0); + this._drawClusters(clusters, dr[0]); this.setCanvasUpdated(); } else { this._animated = false; @@ -533,8 +554,19 @@ ClusterLayer.registerRenderer('canvas', class extends maptalks.renderer.VectorLa } onZoomEnd() { + const zoom = this.getMap().getZoom(); this._animated = true; this._computeGrid(); + if (this._inout === 'in') { + if (!this._clusterCache[zoom + 1]) { + this._clusterCache[zoom + 1] = this._computeZoomGrid(zoom + 1); + } + const tempCluster = this._clusterCache[zoom + 1].clusters; + this._zoomInClusters = []; + for (const p in tempCluster) { + this._zoomInClusters.push(tempCluster[p]); + } + } super.onZoomEnd.apply(this, arguments); }