Hi, At least for markers (not polylines but same technique can apply), we have used the excellent technique developped by marko_rautajoki for that. It is much much faster than core Google Maps Markers, and take 2 to 3 times less memory (indeed low perfs of native Google Maps markers is mainly due to the huge amount of memory required by each marker, average 50K per marker !). See this post : http://groups.google.com/group/google-maps-api-for-flash/browse_thread/thread/52dc36c1a82ba119/22324304b29a1aed?lnk=gst&q=marko_rautajoki#22324304b29a1aed
or directly the example source code there, by viewing source of the example : http://www.elisanet.fi/marko_rautajoki/overlaygrouping/bin-release/gmapPerformanceTest4.html However we have some small issues to solve when using this technique if you want to implement drag/drop, roll over, tooltips, etc. You need to rewrite your own marker class, and then subclass it for concrete use. It is not so complex. Here's is an example of what you can do for this abstract class, took from our own code. Note that some of the code (mouse events on markers) was also written to workaround a google maps with AIR bug described there : http://code.google.com/p/gmaps-api-issues/issues/detail?id=1866 public class VFMarker extends Sprite { public static var MARKER_DRAG_START:String = "VFMarker.DragStart"; public static var MARKER_DRAG_STOP:String = "VFMarker.DragStop"; public static var MARKER_DRAG_STEP:String = "VFMarker.DragStep"; public static var MARKER_CLICK:String = "VFMarker.Click"; public static var MARKER_DOUBLE_CLICK:String = "VFMarker.DoubleClick"; public static var MARKER_ROLL_OVER:String = "VFMarker.RollOver"; public static var MARKER_ROLL_OUT:String = "VFMarker.RollOut"; public static var DRAG_START_EVENT_CODE:uint = 0x01; public static var DRAG_STOP_EVENT_CODE:uint = 0x02; public static var CLICK_EVENT_CODE:uint = 0x04; public static var DOUBLE_CLICK_EVENT_CODE:uint = 0x08; public static var DRAG_STEP_EVENT_CODE:uint = 0x10; public static var ROLL_OVER_EVENT_CODE:uint = 0x20; public static var ROLL_OUT_EVENT_CODE:uint = 0x40; private static var _markerClicked:VFMarker=null; // the last marker clicked (to block mose map clicks) private static var _iconList:Array = new Array; // the list of different colored version of the marker, this is for optimisatino purpose (avoiding recoloring each marker individually) private static var _displayToolTips:Boolean = false; // if true, tooltips will be displayed. If false tooltip text is display in window status label private static var _draggingMarker:VFMarker = null; // internal variable to detect when dragging has really started private var _latLng : LatLng; // marker current position on the map private var _vo:IVOWithMarkers; // the associated VO of the marker (e.g. Employee, Site, etc.) private var _pane:Pane; // the pane on which the marker is private var _listenEventsCodes:uint; // the list of events that we want to follow for this marker private var _toolTip:ToolTipOverlay; // the tooltip associated to the marker private var _toolTipText:String; // the current tooltip text of the marker private var _draggable:Boolean = false; // if marker is draggable or not private var _offset:Point; // (to top left)the offset for this marker (to adjust latLng real position and where the marker is drawn, equivalent to MarkerOptions.ALIGN constants private var _selected:Boolean = false; // if selected this will change marker private var _window:VFNativeWindow;// the mapView window in which the marker is private var _toolTipToogle:Boolean;// this to avoid toolTip blinking private var _emitDragStep:Boolean = false;//if true emit dragStep event private var _wasDraggingTime:int=0; // to avoid markerClicks just after dragging private var _color:uint=Color.WHITE;// curent marker color public function VFMarker(aVO:IVOWithMarkers,aLatLng:LatLng,pane:Pane=null,listenEvents:uint=0) { latLng = aLatLng; _vo = aVO; _vo.addMarker(this); _listenEventsCodes = listenEvents; _pane=pane; _window = pane.mapViewVO.window; _selected = aVO.selected; // this to reflect selection status of markers of a vo at pane load time if (aVO.selected) _pane.selectVO(aVO); // to store the selected VO on pane refreshToolTipText(); buttonMode = true; // this allow to have the hand cursor when roll over on the marker. offset=new Point(-16,-16); // by default marker center. Should be overriden most of time _color=Color.WHITE; // enable listeners depending on listenEvents table if (listenEvents&DRAG_START_EVENT_CODE) { this.addEventListener(MouseEvent.MOUSE_DOWN,mouseDownOnMarker); } if (listenEvents&DRAG_STOP_EVENT_CODE) { this.addEventListener(MouseEvent.MOUSE_UP,mouseUpOnMarker); } if (listenEvents&DOUBLE_CLICK_EVENT_CODE) { this.addEventListener(MouseEvent.DOUBLE_CLICK,markerDoubleClick); } if (listenEvents&CLICK_EVENT_CODE) { this.addEventListener(MouseEvent.CLICK,markerClick); } _emitDragStep = ((listenEvents&DRAG_STEP_EVENT_CODE)!=0); this.addEventListener(MouseEvent.MOUSE_OVER,onMouseOver); this.addEventListener(MouseEvent.MOUSE_OUT,onMouseOut); } /** * called when marker is removed, to remove the listeners * */ public function onRemove():void { if (_listenEventsCodes&DRAG_START_EVENT_CODE) this.removeEventListener(MouseEvent.MOUSE_DOWN,mouseDownOnMarker); if (_listenEventsCodes&DRAG_STOP_EVENT_CODE) this.removeEventListener(MouseEvent.MOUSE_UP,mouseUpOnMarker); if (_listenEventsCodes&CLICK_EVENT_CODE) this.removeEventListener(MouseEvent.CLICK,markerClick); if (_listenEventsCodes&DOUBLE_CLICK_EVENT_CODE) this.removeEventListener(MouseEvent.DOUBLE_CLICK,markerDoubleClick); this.removeEventListener(MouseEvent.MOUSE_OVER,onMouseOver); this.removeEventListener(MouseEvent.MOUSE_OUT,onMouseOut); _vo.removeMarker(this); // to maintain markers collections in vos (Employee, POIs) } /** * Call when change the name * */ public function refreshToolTipText():void { } // display tooltip. override this to do other things protected function onMouseOver(event:MouseEvent):void { if (_displayToolTips) { if (!_toolTip) { _toolTip = new ToolTipOverlay(latLng,_toolTipText); gpane.addOverlay(_toolTip); } _toolTipToogle= false; } else { _window.setStatusLabel(_toolTipText); } if ((_listenEventsCodes&ROLL_OVER_EVENT_CODE)==ROLL_OVER_EVENT_CODE) { sendEvent(MARKER_ROLL_OVER,latLng); } } // remove tooltip. override this to do other things protected function onMouseOut(event:MouseEvent):void { if (_displayToolTips) { if (_toolTip) { if (_toolTipToogle) { gpane.removeOverlay(_toolTip); _toolTip = null; } else { _toolTipToogle= true; var timer:Timer = new Timer(1000,1); timer.addEventListener(TimerEvent.TIMER,function (e:TimerEvent):void { if (_toolTip) { gpane.removeOverlay(_toolTip); _toolTip = null; } }); timer.start(); } } } else { if (!draggingMarker) { _window.setStatusLabel(""); } } if ((_listenEventsCodes&ROLL_OUT_EVENT_CODE)==ROLL_OUT_EVENT_CODE) { sendEvent(MARKER_ROLL_OUT,latLng); } } // send event markers into application. private function sendEvent(eventName:String,latLng:LatLng):void { dispatchEvent(new VFMarkerEvent(eventName,this,latLng)); } /** * the base icon, that will be eventually colored, then getIcon may draw additional things on top of icon * @return * */ protected function getIconBase():Bitmap { return new Bitmap(); } /** * get the icon of the marker. * will color the marker with passed fillstyle, if any * @param fillStyle * @return * */ public function getIcon(afillStyle:VFFillStyle=null):Bitmap { var resultIcon:Bitmap = getIconBase(); var objectKey:ByteArray = new ByteArray(); if (!afillStyle) { afillStyle = new VFFillStyle(); afillStyle.color = _color;} // if no fillstyle, use previous color (it is a refresh on select or unselect) //change icon color, if different from white if (afillStyle.color!=Color.WHITE || afillStyle.colors.length>1) { _color = afillStyle.color; // build icon key : the icon class name + color : if same class name and color, do not recolorize (it takes time). objectKey.writeObject(Object(resultIcon).constructor.toString()); if (afillStyle.colors.length<=1) { afillStyle.colors=[_color]; } objectKey.writeObject(afillStyle.colors); //do not change color for each icon, but only for each new Icon with a new fillstyle if (_iconList[objectKey]==null) { UtilityFunctions.changeIconFillColor(Bitmap(resultIcon).bitmapData,afillStyle.colors,Number(afillStyle.alpha)); _iconList[objectKey] = Bitmap(resultIcon).bitmapData; // store new colored icon in dictionary } resultIcon.bitmapData =_iconList[objectKey].clone(); // must clone as it is different instances of bitmap data } return resultIcon; } /** * recompute the marker position (x,y) on positionWatcher, according to latLng * */ public function computeMarkerPosition():void { var position : Point; if (!pane.is3D) { position = pane.gpane.fromLatLngToPaneCoords( latLng ); } else { position = pane.positionWatcher.getPointForLatLng3D( latLng ); } x = position.x+offset.x; y = position.y+offset.y; } /** * recompute latLng according to point * */ public function computeLatLngFromPoint():void { if (pane.is3D) { latLng = pane.positionWatcher.getLatLngForPointIn3DMap(point); } else { latLng = pane.gpane.fromPaneCoordsToLatLng(point); } } /** * call this to redraw the marker if icon or style changes. * @param fillStyle * */ public function refresh(fillStyle:VFFillStyle=null,size:uint=32):void { var g : Graphics = this.graphics; g.clear(); //to clear the garphics before drawing. g.beginBitmapFill(getIcon(fillStyle).bitmapData,null,false); g.drawRect( 0, 0, size, size ); //draw the bitmap in the rectangle g.endFill(); //end draw the bitmap if (_selected) { //If the marker is selected, draw a circle out of the bitmap g.lineStyle(2,0,1,true); g.drawCircle(size/2-1,size/2-1,size/2-2); } } public function select():void { if (!_selected) { _selected = true; refresh(); if (pane.positionWatcher.numChildren>0 && (pane.markers.indexOf(this)>=0)) { // must be added already on pane pane.positionWatcher.setChildIndex(this,pane.positionWatcher.numChildren-1); // put it in front } } } public function unselect():void { if (_selected) { FSTrace.fsTrace("marker unselect "+vo.name+" "+vo.latLng+" pane "+pane.name); _selected = false; refresh(); } } // start dragging the marker (in reality drag really start at the first MOUSE_MOVE protected function mouseDownOnMarker(event:MouseEvent):void { _markerClicked = this; if (_draggable) { _draggingMarker=null; addEventListener(MouseEvent.MOUSE_MOVE,onDuringDrag); startDrag(); } } // to detecte real start of dragging protected function onDuringDrag(event:MouseEvent):void { if (!_draggingMarker) { _draggingMarker = this; sendEvent(MARKER_DRAG_START,latLng); } else { var aLatLng:LatLng = gpane.fromPaneCoordsToLatLng(new Point(event.stageX,event.stageY)); _window.setStatusLabel("Lat : "+aLatLng.lat().toFixed(6)+" Lng : "+aLatLng.lng().toFixed(6)); if (_emitDragStep) { sendEvent(MARKER_DRAG_STEP,aLatLng); } } } // end of dragging protected function mouseUpOnMarker(event:MouseEvent):void { FSTrace.fsTrace("mouseUpOnMarker "+latLng+" x "+x+" y "+y+" event.localX "+event.localX+" event.localY "+event.localY); stopDrag(); removeEventListener(MouseEvent.MOUSE_MOVE,onDuringDrag); if (_draggingMarker) { _window.setStatusLabel(""); _draggingMarker=null; _markerClicked=null; _wasDraggingTime=getTimer(); latLng = gpane.fromPaneCoordsToLatLng(new Point(event.stageX,event.stageY)); sendEvent(MARKER_DRAG_STOP,latLng); } } // this to correct a bug somtimes the mouseUp on marker is not detected, replaced by a mouseUp on map public function triggerMouseUp(event:MouseEvent):void { mouseUpOnMarker(event); } /** * @param event the MapMouseEvent. */ protected function markerClick(event:MouseEvent):void { if ((getTimer()-_wasDraggingTime)>500) { // to avoid marker click events at the end of dragging FSTrace.fsTrace("VFMarker.markerClick"); _markerClicked = this; sendEvent(MARKER_CLICK,latLng); } } /** * @param event the MapMouseEvent. */ protected function markerDoubleClick(event:MouseEvent):void { sendEvent(MARKER_DOUBLE_CLICK,latLng); } /****************************************** ACCESSORS ********************************/ public function get toolTip():ToolTipOverlay { return _toolTip; } public function set toolTip(value:ToolTipOverlay):void { _toolTip = value; } public function get vo():IVOWithMarkers { return _vo; } public function set vo(value:IVOWithMarkers):void { _vo = value; } public function get gpane():IPane { return _pane.gpane; } public function get pane():Pane { return _pane; } public function get draggable():Boolean { return _draggable; } public function set draggable(value:Boolean):void { _draggable = value; } public function get latLng():LatLng { return _latLng; } public function set latLng(value:LatLng):void { _latLng = value; } public function get toolTipText():String { return _toolTipText; } public function set toolTipText(value:String):void { _toolTipText = value; } public function get offset():Point { return _offset; } public function set offset(value:Point):void { _offset = value; } public static function get markerClicked():VFMarker { return _markerClicked; } public static function set markerClicked(value:VFMarker):void { _markerClicked = value; } public function get selected():Boolean { return _selected; } /** * default menu data for contextual menu of markers * need to override this * @return * */ public function get menuData():XML { return null; } /** * return true point position removing offset from marker x,y * @return * */ public function get point():Point { return new Point(x-offset.x,y-offset.y); } public static function get displayToolTips():Boolean { return _displayToolTips; } public static function set displayToolTips(value:Boolean):void { _displayToolTips = value; } protected function get window():VFNativeWindow { return _window; } public static function get draggingMarker():VFMarker { return _draggingMarker; } } } Cédric NICOLAS www.villefluide.fr On 18 oct, 12:30, Engendrix <[email protected]> wrote: > Hi there, > > I´m developing an app on AS3 and I need to place about 3000 of markers > an 7000 connections (polylines) between those markers. When I load > just about 100 markers, the app runs ok but when I try to load all of > them, it slows down and doesn´t work properly. > I have already read some about markerManager, but I need all the > markers to be shown in all zoom levels. > Can anyone help me with this issue? I´m thinking of doing it in google > Earth, but this will be start from the beginning agaim. Any Idea or > suggestion? > > Thanks for your time. -- You received this message because you are subscribed to the Google Groups "Google Maps API For Flash" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/google-maps-api-for-flash?hl=en.
