For the past year, I have been working on a client project that utilized the Google Maps for Flash API. One issue that I hoped to address was the sluggishness that results from instantiating 100+ instances of com.google.map.overlays.Marker. The forums have a few threads discussing this topic. Digging into them, you immediately get the idea to not use Google’s Marker class, but rather a single instance of a custom class you create that extends OverlayBase. This class would then create markers as instances of Sprite. You would override the OverlayBase’s positionOverlay() method to reposition your markers. This technique allowed us to achieve a few hundred interactive markers before the application became noticeably sluggish.
Getting to the next level of supporting 1,000+ interactive markers, however, was a much more difficult task. There was this thread, where Jonathan Wagner described the use of bitmap tiles. He went further by providing an example and sharing his code. Unfortunately, while the example achieved an ultra-high number of markers, the markers were not interactive. However, it certainly pointed me in the right direction.
Basically, what you need to do is create 256 x 256 bitmaps that will exactly overlay the 256 x 256 bitmap tiles that Google serves up for their map.

When each marker was its own instance of Sprite, you could easily register event listeners for the MouseEvents. However, with a bitmap that can contain several markers, you have to get more creative. More on that below.
The classes are:
- Marker.as
- MarkerGroup.as
- MarkerTileLayer.as
- Tile.as
Your application creates an instance of MarkerTileLayer. It also creates an instance of com.google.maps.overlays.TileLayerOverlay, passing in the MarkerTileLayer as a parameter.
PerformanceMarkers.mxml
-
markerTileLayer = new MarkerTileLayer(map);
-
tileLayerOverlay = new TileLayerOverlay(markerTileLayer);
-
tileLayerOverlay.addEventListener(MapEvent.TILES_LOADED, tileLayerOverlay_tilesLoadedHandler);
-
map.addOverlay(tileLayerOverlay);
-
addMarkers();
The TILES_LOADED event listener is important because it is how we keep the number of Tile instances under control by calling markerTileLayer.disposeOffscreenCachedTiles().
In the addMarkers() method, I create instances of Marker. The constructor takes two parameters: the LatLng and BitmapData. I add the event listeners for Marker.MARKER_CLICK and Marker.MARKER_HOVER directly to the Marker instances.
So my application only deals directly with two of the four classes in the above list: MarkerTileLayer and Marker.
MarkerTileLayer deals with the other two classes: MarkerGroup and Tile.
MarkerGroup is pretty simple. It is a group of Marker objects that are contained by a LatLngBounds. Both of these are passed into the MarkerGroup constructor. It then exposes a public method whose signature is containsMarker(marker:Marker):Boolean.
Tile is more complex. Tile extends Sprite and is the DisplayObject that gets returned from MarkerTileLayer.loadTile().
MarkerTileLayer has a setter for the markers Array. This is where I break up the Markers into MarkerGroups. I use MarkerGroups so that the MarkerTileLayer.loadTile() method does not have to cycle through every Marker instance to check if it should be rendered onto that Tile. Instead, it can check a smaller number of MarkerGroups. If the MarkerGroup’s latLngBounds does not intersect the Tile, then the entire MarkerGroup can be skipped.
When a marker is clicked, figuring out which marker is tricky. You just need to register an event listener on the Marker instance for Marker.MARKER_CLICK, but underneath the hood MarkerTileLayer has event listeners on the Tile. When a Tile is clicked, it must determine which Marker. It does this in the method Tile.getTopmostMarkerAtPoint().
One issue I have found is that if a Marker has a pixel with an alpha value of less than 1.0, and that pixel is the one clicked, and the Marker overlaps another Marker, then the Tile.getTopmostMarkerAtPoint() does not return the Marker (and thus the Marker does not dispatch any event).
I have commented the code pretty well. Here are the application and source code. Be sure to try a larger number of markers than the default 500. On my machine, performance is excellent up to 5,000 and still very good at 10,000 and 20,000 (with only a slight stutter when zooming).
A major challenge is still animated markers. I have a solution to accommodate limited animation (4 frames) which I hope to go over in a future blog post. Basically each Tile has 4 BitmapData objects and swaps them out on the ENTER_FRAME event.

Curious Find is the website of Jamie McDaniel, a freelance iOS developer located in Lexington, Kentucky.
Hi
Is there a way of bringing in Kml files into flash. Im sure the upload time will be much faster just like in google maps. Is this possible?
This is Awesome!! thank you very much for sharing this!!
Hey , thanks so much for this example. It really helped out. I was wondering if you had ever had problems with firing mouseEvents under a TileLayerOverlay. We are using the TileLayerOverlay class and the mouseEvents under the TileLayerOVerLay will not fire. It has to be some displayobject blocking the events. I havent been able to fix this yet. Seemed like an easy fix :
var layer:Sprite = tilerLayerOver.foreground as Sprite;
layer.mouseChildren = true;
something like that seemed like it should fix the problem and of course no dice.. Hope this makes sense? If you have any info on this or know of a link to something i could read about that would be great..
Again thanks so much for this example..
chris.
Hi! I got a problem with embedding your stuff into an air application….
as soon as i try to push a marker and the refresh the tileLayerOverlay i get a
SecurityError: Error #2047: Security sandbox violation: parent: http://maps.googleapis.com/mapfiles/lib/map_1_20.swf cannot access app:/main.swf
=( i really don’t know what to do