/src/com/google/maps/extras/markerclusterer/ClusterMarker.as
ActionScript | 241 lines | 100 code | 35 blank | 106 comment | 4 complexity | 82c2ce9167a2e042dc39ff5d7336ce43 MD5 | raw file
1/** 2 * @name MarkerClusterer for Flash 3 * @version 1.0 4 * @author Xiaoxi Wu 5 * @copyright (c) 2009 Xiaoxi Wu 6 * @fileoverview 7 * Ported from Javascript to Actionscript 3 by Sean Toru 8 * Ported for use in Flex (removal of fl. libraries) by Ian Watkins 9 * Reflectored for both Flash and Flex, 10 * and maintained by Juguang XIAO (juguang@gmail.com) 11 * 12 * This actionscript library creates and manages per-zoom-level 13 * clusters for large amounts of markers (hundreds or thousands). 14 * This library was inspired by the <a href="http://www.maptimize.com"> 15 * Maptimize</a> hosted clustering solution. 16 * <br /><br/> 17 * <b>How it works</b>:<br/> 18 * The <code>MarkerClusterer</code> will group markers into clusters according to 19 * their distance from a cluster's center. When a marker is added, 20 * the marker cluster will find a position in all the clusters, and 21 * if it fails to find one, it will create a new cluster with the marker. 22 * The number of markers in a cluster will be displayed 23 * on the cluster marker. When the map viewport changes, 24 * <code>MarkerClusterer</code> will destroy the clusters in the viewport 25 * and regroup them into new clusters. 26 * 27 */ 28 29/* 30 * Licensed under the Apache License, Version 2.0 (the "License"); 31 * you may not use this file except in compliance with the License. 32 * You may obtain a copy of the License at 33 * 34 * http://www.apache.org/licenses/LICENSE-2.0 35 * 36 * Unless required by applicable law or agreed to in writing, software 37 * distributed under the License is distributed on an "AS IS" BASIS, 38 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 39 * See the License for the specific language governing permissions and 40 * limitations under the License. 41 */ 42 43package com.google.maps.extras.markerclusterer 44{ 45import com.google.maps.LatLng; 46import com.google.maps.MapEvent; 47import com.google.maps.interfaces.IMap; 48import com.google.maps.interfaces.IPane; 49import com.google.maps.interfaces.IPaneManager; 50import com.google.maps.overlays.OverlayBase; 51 52import flash.display.Bitmap; 53import flash.display.Loader; 54import flash.events.Event; 55import flash.geom.Point; 56import flash.net.URLRequest; 57import flash.text.TextField; 58import flash.text.TextFormat; 59import flash.text.TextFormatAlign; 60 61 62/** 63 * 64 * This is a presentation class for <code>Cluster</code>. 65 * The current implementation is to load images for different level. 66 * Later, it can be implemented with other possibilities. 67 * 68 * 69 * Update: 70 * 2010-02-11 71 * Now it works with Flash, that means it also works for Flex. 72 * 2010-02-13 73 * Make it formal as overlay .e.g. create and destroy content as needed - 74 * through MapEvent.OVERLAY_ADDED, and MapEvent.OVERLAY_REMOVED events. 75 */ 76internal class ClusterMarker extends OverlayBase 77{ 78 private var _latlng : LatLng; 79 private var _count : int; 80 private var _styles : Array; 81// private var text_ : String; 82// private var padding_ : Number; 83 84 85// private var imageLoader : Image; 86// private var label : Label; 87 88 public function ClusterMarker (latlng : LatLng, count:int , styles : Array, padding : Number) 89 { 90 _latlng = latlng; 91 _styles = styles; 92 _count = count; 93 94 this.addEventListener(MapEvent.OVERLAY_ADDED, onOverlayAdded); 95 this.addEventListener(MapEvent.OVERLAY_REMOVED, onOverlayRemoved); 96 97 } 98 99 private var _ld:Loader; 100 private var _tf:TextField; 101 102 private function onOverlayAdded(event:MapEvent):void{ 103 var index : int = 0; 104 var dv : int = _count; 105 106 while (dv != 0) { 107 dv = dv / 10; 108 index ++; 109 } 110 111 if (_styles.length < index) { 112 index = _styles.length; 113 } 114 115 var url_ :String = _styles[index - 1].url; 116// textColor_ = styles[index - 1].opt_textColor; 117// anchor_ = styles[index - 1].opt_anchor; 118 119 var text_:String = String(_count); 120// padding_ = padding; 121/* 122 imageLoader = new Image(); 123 imageLoader.autoLoad = true; 124 imageLoader.source = url_; 125 imageLoader.scaleContent = false; 126 imageLoader.addEventListener(Event.COMPLETE, completeHandler); 127 addChild(imageLoader); 128 */ 129 var req:URLRequest = new URLRequest(url_); 130 _ld = new Loader; 131 _ld.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler); 132 _ld.load(req); 133 134 this.addChild(_ld); 135 136 137/* 138@20100211 139Previous code, for Flex only! 140 label = new Label(); 141 label.setStyle("textAlign", "center"); 142 label.setStyle("color", "0x00FF00"); 143 label.setStyle("font", "Verdana"); 144 label.setStyle("bold", "true"); 145 label.selectable = false; 146 label.text = text_; 147 148 addChild(label); 149 */ 150 var format :TextFormat = new TextFormat; 151 format.align = TextFormatAlign.CENTER; 152 format.color = 0xFFFFFF; 153 format.font = 'Verdana'; 154 format.bold = true; 155 156 this._tf = new TextField; 157 _tf.selectable = false; 158 _tf.text = text_; 159 _tf.setTextFormat(format); 160 161 this.addChild(_tf); 162 } 163 164 private function onOverlayRemoved(event:MapEvent):void{ 165 this.removeChild(_ld); 166 _ld = null; 167 168 this.removeChild(_tf); 169 _tf = null; 170 171 } 172 173 private function completeHandler(event : Event) : void 174 { 175 // imageLoader.width = event.currentTarget.content.width; 176 // imageLoader.height = event.currentTarget.content.height; 177 var content:Bitmap = event.currentTarget.content; 178 _ld.width = content.width; 179 _ld.height = content.height; 180 181 // event.currentTarget.move(imageLoader.width/-2, imageLoader.height/-2); 182 _ld.x = _ld.width / -2; 183 _ld.y = _ld.height / -2; 184 185 /* label.width = imageLoader.width; 186 label.height = 14; 187 label.x = imageLoader.width / -2; 188 label.y = 0 - (label.height / 2); 189 label.visible = true; */ 190 this._tf.width = _ld.width; 191 this._tf.height = 16; 192 this._tf.x = - _ld.width / 2; 193 this._tf.y = 0 - (_tf.height/2); 194 195 } 196 197 override public function getDefaultPane(map : IMap): IPane 198 { 199 var paneManager : IPaneManager = map.getPaneManager(); 200 201// return paneManager.getPaneById(PaneId.PANE_MARKER); 202 203 return null; 204 } 205 206 override public function positionOverlay(zoomChanged : Boolean): void 207 { 208 this.reposition(); 209 } 210 211/* private function remove () : void 212 { 213 parent.removeChild(this); 214 } */ 215 /* 216 private function copy () : ClusterMarker 217 { 218 return new ClusterMarker(this.latlng_, this.index_, this.styles_, this.padding_); 219 } 220 */ 221 /** 222 * 223 * Developer should not call this function. 224 * It is managed by Cluster. 225 */ 226 internal function redraw (force:Boolean) : void 227 { 228 if (!force){ 229 return; 230 } 231 232 this.reposition(); 233 } 234 235 private function reposition():void{ 236 var pos : Point = this.pane.fromLatLngToPaneCoords(_latlng); 237 x = pos.x; 238 y = pos.y; 239 } 240} 241}