Sei sulla pagina 1di 6

/* ClusterMarker Version 1.3.

0 modified to only create a cluster marker if a cluster exceeds a (preset) number of markers new constructor option minClusterSize added if minClusterSize not specified when ClusterMarker created then a cluste r marker is created whenever 2 or more markers intersect see http://googlemapsapi.martinpearman.co.uk/forum/viewthread.php?forum_ id=5&thread_id=10&pid=27#post_27 A marker manager for the Google Maps API http://googlemapsapi.martinpearman.co.uk/clustermarker Copyright Martin Pearman 2008 Last updated 25th August 2008 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Softw are Foundation, either version 3 of the License, or (at your option) any later v ersion. This program is distributed in the hope that it will be useful, but WITH OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNES S FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details . You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ function ClusterMarker($map, $options){ this._map=$map; this._mapMarkers=[]; this._iconBounds=[]; this._clusterMarkers=[]; this._eventListeners=[]; if(typeof($options)==='undefined'){ $options={}; } this.borderPadding=($options.borderPadding)?$options.borderPadding:256; this.clusteringEnabled=($options.clusteringEnabled===false)?false:true; if($options.clusterMarkerClick){ this.clusterMarkerClick=$options.clusterMarkerClick; } if($options.clusterMarkerIcon){ this.clusterMarkerIcon=$options.clusterMarkerIcon; }else{ this.clusterMarkerIcon=new GIcon(); this.clusterMarkerIcon.image='http://maps.google.com/mapfiles/ar row.png'; this.clusterMarkerIcon.iconSize=new GSize(39, 34); this.clusterMarkerIcon.iconAnchor=new GPoint(9, 31); this.clusterMarkerIcon.infoWindowAnchor=new GPoint(9, 31); this.clusterMarkerIcon.shadow='http://www.google.com/intl/en_us/ mapfiles/arrowshadow.png'; this.clusterMarkerIcon.shadowSize=new GSize(39, 34); } this.clusterMarkerTitle=($options.clusterMarkerTitle)?$options.clusterMa

rkerTitle:'Click to zoom in and see %count markers'; if($options.fitMapMaxZoom){ this.fitMapMaxZoom=$options.fitMapMaxZoom; } this.intersectPadding=($options.intersectPadding)?$options.intersectPadd ing:0; if($options.markers){ this.addMarkers($options.markers); } this.minClusterSize=($options.minClusterSize)?$options.minClusterSize:1; GEvent.bind(this._map, 'moveend', this, this._moveEnd); GEvent.bind(this._map, 'zoomend', this, this._zoomEnd); GEvent.bind(this._map, 'maptypechanged', this, this._mapTypeChanged); } ClusterMarker.prototype.addMarkers=function($markers){ var i; if(!$markers[0]){ // assume $markers is an associative array and convert to a numerically indexed array var $numArray=[]; for(i in $markers){ $numArray.push($markers[i]); } $markers=$numArray; } for(i=$markers.length-1; i>=0; i--){ $markers[i]._isVisible=false; $markers[i]._isActive=false; $markers[i]._makeVisible=false; } this._mapMarkers=this._mapMarkers.concat($markers); }; ClusterMarker.prototype._clusterMarker=function($clusterGroupIndexes){ function $newClusterMarker($location, $icon, $title){ return new GMarker($location, {icon:$icon, title:$title}); } var $clusterGroupBounds=new GLatLngBounds(), i, $clusterMarker, $cluster edMarkers=[], $marker, $this=this; for(i=$clusterGroupIndexes.length-1; i>=0; i--){ $marker=this._mapMarkers[$clusterGroupIndexes[i]]; $marker.index=$clusterGroupIndexes[i]; $clusterGroupBounds.extend($marker.getLatLng()); $clusteredMarkers.push($marker); } $clusterMarker=$newClusterMarker($clusterGroupBounds.getCenter(), this.c lusterMarkerIcon, this.clusterMarkerTitle.replace(/%count/gi, $clusterGroupIndex es.length)); $clusterMarker.clusterGroupBounds=$clusterGroupBounds; this._eventListeners.push(GEvent.addListener($clusterMarker, 'click', fu nction(){ $this.clusterMarkerClick({clusterMarker:$clusterMarker, clustere dMarkers:$clusteredMarkers }); })); return $clusterMarker; }; ClusterMarker.prototype.clusterMarkerClick=function($args){ this._map.setCenter($args.clusterMarker.getLatLng(), this._map.getBounds

ZoomLevel($args.clusterMarker.clusterGroupBounds)); }; ClusterMarker.prototype._filterActiveMapMarkers=function(){ var $borderPadding=this.borderPadding, $mapZoomLevel=this._map.getZoom() , $mapProjection=this._map.getCurrentMapType().getProjection(), $mapPointSw, $ac tiveAreaPointSw, $activeAreaLatLngSw, $mapPointNe, $activeAreaPointNe, $activeAr eaLatLngNe, $activeAreaBounds=this._map.getBounds(), i, $marker, $uncachedIconBo undsIndexes=[], $oldState; if($borderPadding){ $mapPointSw=$mapProjection.fromLatLngToPixel($activeAreaBounds.g etSouthWest(), $mapZoomLevel); $activeAreaPointSw=new GPoint($mapPointSw.x-$borderPadding, $map PointSw.y+$borderPadding); $activeAreaLatLngSw=$mapProjection.fromPixelToLatLng($activeArea PointSw, $mapZoomLevel); $mapPointNe=$mapProjection.fromLatLngToPixel($activeAreaBounds.g etNorthEast(), $mapZoomLevel); $activeAreaPointNe=new GPoint($mapPointNe.x+$borderPadding, $map PointNe.y-$borderPadding); $activeAreaLatLngNe=$mapProjection.fromPixelToLatLng($activeArea PointNe, $mapZoomLevel); $activeAreaBounds.extend($activeAreaLatLngSw); $activeAreaBounds.extend($activeAreaLatLngNe); } this._activeMarkersChanged=false; if(typeof(this._iconBounds[$mapZoomLevel])==='undefined'){ this._iconBounds[$mapZoomLevel]=[]; this._activeMarkersChanged=true; for(i=this._mapMarkers.length-1; i>=0; i--){ $marker=this._mapMarkers[i]; $marker._isActive=$activeAreaBounds.containsLatLng($mark er.getLatLng())?true:false; $marker._makeVisible=$marker._isActive; if($marker._isActive){ $uncachedIconBoundsIndexes.push(i); } } }else{ for(i=this._mapMarkers.length-1; i>=0; i--){ $marker=this._mapMarkers[i]; $oldState=$marker._isActive; $marker._isActive=$activeAreaBounds.containsLatLng($mark er.getLatLng())?true:false; $marker._makeVisible=$marker._isActive; if(!this._activeMarkersChanged && $oldState!==$marker._i sActive){ this._activeMarkersChanged=true; } if($marker._isActive && typeof(this._iconBounds[$mapZoom Level][i])==='undefined'){ $uncachedIconBoundsIndexes.push(i); } } } return $uncachedIconBoundsIndexes; }; ClusterMarker.prototype._filterIntersectingMapMarkers=function(){ var $clusterGroup, i, j, $mapZoomLevel=this._map.getZoom(), $minClusterS

ize=this.minClusterSize; for(i=this._mapMarkers.length-1; i>0; i--) { if(this._mapMarkers[i]._makeVisible){ $clusterGroup=[]; for(j=i-1; j>=0; j--){ if(this._mapMarkers[j]._makeVisible && this._ico nBounds[$mapZoomLevel][i].intersects(this._iconBounds[$mapZoomLevel][j])){ $clusterGroup.push(j); } } if($clusterGroup.length>=$minClusterSize){ $clusterGroup.push(i); for(j=$clusterGroup.length-1; j>=0; j--){ this._mapMarkers[$clusterGroup[j]]._make Visible=false; } this._clusterMarkers.push(this._clusterMarker($c lusterGroup)); } } } }; ClusterMarker.prototype.fitMapToMarkers=function(){ var $markers=this._mapMarkers, $markersBounds=new GLatLngBounds(), i; for(i=$markers.length-1; i>=0; i--){ $markersBounds.extend($markers[i].getLatLng()); } var $fitMapToMarkersZoom=this._map.getBoundsZoomLevel($markersBounds); if(this.fitMapMaxZoom && $fitMapToMarkersZoom>this.fitMapMaxZoom){ $fitMapToMarkersZoom=this.fitMapMaxZoom; } this._map.setCenter($markersBounds.getCenter(), $fitMapToMarkersZoom); this.refresh(); }; ClusterMarker.prototype._mapTypeChanged=function(){ this.refresh(true); }; ClusterMarker.prototype._moveEnd=function(){ if(!this._cancelMoveEnd){ this.refresh(); }else{ this._cancelMoveEnd=false; } }; ClusterMarker.prototype._preCacheIconBounds=function($indexes){ var $mapProjection=this._map.getCurrentMapType().getProjection(), $mapZo omLevel=this._map.getZoom(), i, $marker, $iconSize, $iconAnchorPoint, $iconAncho rPointOffset, $iconBoundsPointSw, $iconBoundsPointNe, $iconBoundsLatLngSw, $icon BoundsLatLngNe, $intersectPadding=this.intersectPadding; for(i=$indexes.length-1; i>=0; i--){ $marker=this._mapMarkers[$indexes[i]]; $iconSize=$marker.getIcon().iconSize; $iconAnchorPoint=$mapProjection.fromLatLngToPixel($marker.getLat Lng(), $mapZoomLevel);

$iconAnchorPointOffset=$marker.getIcon().iconAnchor; $iconBoundsPointSw=new GPoint($iconAnchorPoint.x-$iconAnchorPoin tOffset.x-$intersectPadding, $iconAnchorPoint.y-$iconAnchorPointOffset.y+$iconSi ze.height+$intersectPadding); $iconBoundsPointNe=new GPoint($iconAnchorPoint.x-$iconAnchorPoin tOffset.x+$iconSize.width+$intersectPadding, $iconAnchorPoint.y-$iconAnchorPoint Offset.y-$intersectPadding); $iconBoundsLatLngSw=$mapProjection.fromPixelToLatLng($iconBounds PointSw, $mapZoomLevel); $iconBoundsLatLngNe=$mapProjection.fromPixelToLatLng($iconBounds PointNe, $mapZoomLevel); this._iconBounds[$mapZoomLevel][$indexes[i]]=new GLatLngBounds($ iconBoundsLatLngSw, $iconBoundsLatLngNe); } }; ClusterMarker.prototype.refresh=function($forceFullRefresh){ var i,$marker, $uncachedIconBoundsIndexes=this._filterActiveMapMarkers() ; if(this._activeMarkersChanged $forceFullRefresh){ this._removeClusterMarkers(); if(this.clusteringEnabled && this._map.getZoom()<this._map.getCu rrentMapType().getMaximumResolution()){ if($uncachedIconBoundsIndexes.length>0){ this._preCacheIconBounds($uncachedIconBoundsInde xes); } this._filterIntersectingMapMarkers(); } for(i=this._clusterMarkers.length-1; i>=0; i--){ this._map.addOverlay(this._clusterMarkers[i]); } for(i=this._mapMarkers.length-1; i>=0; i--){ $marker=this._mapMarkers[i]; if(!$marker._isVisible && $marker._makeVisible){ this._map.addOverlay($marker); $marker._isVisible=true; } if($marker._isVisible && !$marker._makeVisible){ this._map.removeOverlay($marker); $marker._isVisible=false; } } } }; ClusterMarker.prototype._removeClusterMarkers=function(){ for(var i=this._clusterMarkers.length-1; i>=0; i--){ this._map.removeOverlay(this._clusterMarkers[i]); } for(i=this._eventListeners.length-1; i>=0; i--){ GEvent.removeListener(this._eventListeners[i]); } this._clusterMarkers=[]; this._eventListeners=[]; }; ClusterMarker.prototype.removeMarkers=function(){ for(var i=this._mapMarkers.length-1; i>=0; i--){ if(this._mapMarkers[i]. _isVisible){

this._map.removeOverlay(this._mapMarkers[i]); } delete this._mapMarkers[i]._isVisible; delete this._mapMarkers[i]._isActive; delete this._mapMarkers[i]._makeVisible; } this._removeClusterMarkers(); this._mapMarkers=[]; this._iconBounds=[]; }; ClusterMarker.prototype.triggerClick=function($index){ var $marker=this._mapMarkers[$index]; if($marker._isVisible){ // $marker is visible GEvent.trigger($marker, 'click'); } else if($marker._isActive){ // $marker is clustered this._map.setCenter($marker.getLatLng()); this._map.zoomIn(); this.triggerClick($index); }else{ // $marker is not within active area (map bounds + border paddin g) this._map.setCenter($marker.getLatLng()); this.triggerClick($index); } }; ClusterMarker.prototype._zoomEnd=function(){ this._cancelMoveEnd=true; this.refresh(true); };

Potrebbero piacerti anche