Changeset 622

Show
Ignore:
Timestamp:
07/20/08 17:43:15 (2 months ago)
Author:
tom
Message:

cleanups and refactoring in TileGrid

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/tom-tweenlite/lib/com/modestmaps/core/TileGrid.as

    r621 r622  
    4949                protected var _invertedMatrix:Matrix; // use lazy getter for this 
    5050                 
    51                 // the corners of the screen, in map coordinates 
     51                // the corners and center of the screen, in map coordinates 
    5252                // (these also have lazy getters) 
    5353                protected var _topLeftCoordinate:Coordinate; 
    5454                protected var _bottomRightCoordinate:Coordinate; 
     55                protected var _centerCoordinate:Coordinate; 
    5556 
    5657                // where the tiles live: 
     
    9495 
    9596                // what zoom level of tiles is 'correct'? 
    96                 protected var _currentZoom:int;  
     97                protected var _currentTileZoom:int;  
    9798                // so we know if we're going in or out 
    98                 protected var previousZoom:int;                
     99                protected var previousTileZoom:int;            
    99100                 
    100101                // for sorting the queue: 
     
    222223                } 
    223224 
     225                /** The classes themselves serve as factories! 
     226                 *  
     227                 * @param tileClass e.g. Tile, TweenTile, etc. 
     228                 *  
     229                 * @see http://norvig.com/design-patterns/img013.gif   
     230                 */  
    224231                public function setTileClass(tileClass:Class):void 
    225232                { 
     
    227234                } 
    228235                 
    229                 public function onEnterFrame(event:Event=null):void 
    230                 { 
    231                         // for stats... 
    232                         var frameDuration:Number = getTimer() - lastFrameTime; 
    233                         lastFrameTime = getTimer(); 
    234                          
    235                         fps = (0.9 * fps) + (0.1 * (1000.0/frameDuration)); 
    236  
     236                /** processes the tileQueue and optionally outputs stats into debugField */ 
     237                protected function onEnterFrame(event:Event=null):void 
     238                { 
    237239                        if (debugField.parent) { 
     240                                // for stats... 
     241                                var frameDuration:Number = getTimer() - lastFrameTime; 
     242                                lastFrameTime = getTimer(); 
     243                                 
     244                                fps = (0.9 * fps) + (0.1 * (1000.0/frameDuration)); 
     245         
    238246                                // report stats: 
    239247                                var tileChildren:int = 0; 
     
    267275                } 
    268276                 
     277                /**  
     278                 * figures out from worldMatrix which tiles we should be showing, adds them to the stage, adds them to the tileQueue if needed, etc.  
     279                 */ 
    269280                protected function onRender(event:Event=null):void 
    270281                { 
     
    276287 
    277288                        if (zooming && panning) { 
     289                                // doesn't bubble, unlike MapEvent 
     290                                // Map will pick this up and dispatch MapEvent.EXTENT_CHANGED for us 
    278291                                dispatchEvent(new Event(Event.CHANGE, false, false)); 
    279292                        }  
     
    288301                        }        
    289302                        else if (zooming) { 
    290                         var zoomEvent:MapEvent = new MapEvent(MapEvent.ZOOMED_BY); 
    291                 zoomEvent.zoomDelta = zoomLevel-startZoom; 
     303                        var zoomEvent:MapEvent = new MapEvent(MapEvent.ZOOMED_BY, zoomLevel-startZoom); 
     304                       // this might also be useful 
    292305                zoomEvent.zoomLevel = zoomLevel; 
    293306                dispatchEvent(zoomEvent); 
    294307                        } 
    295308                        else if (boundsEnforced) { 
     309                                // doesn't bubble, unlike MapEvent 
     310                                // Map will pick this up and dispatch MapEvent.EXTENT_CHANGED for us 
    296311                                dispatchEvent(new Event(Event.CHANGE, false, false)); 
    297312                        } 
    298313                         
    299                         // find the extents of the ur-tile: 
    300                         // (where would the top left and bottom right corners of the  
    301                         //  world be now if we only had one tile at zoom level 0?) 
    302                         // TODO deal with what happens with non-square projections! 
    303                         var worldMin:Point = worldMatrix.transformPoint(new Point(0,0)); 
    304                         var worldMax:Point = worldMatrix.transformPoint(new Point(tileWidth, tileHeight)); 
    305  
    306314                        // what zoom level of tiles should we be loading, taking into account min/max zoom? 
    307315                        // (0 when scale == 1, 1 when scale == 2, 2 when scale == 4, etc.) 
     
    310318                        // see if the newZoom is different to currentZoom 
    311319                        // so we know which way we're zooming, if any: 
    312                         if (currentZoom != newZoom) { 
    313                                 previousZoom = currentZoom; 
     320                        if (currentTileZoom != newZoom) { 
     321                                previousTileZoom = currentTileZoom; 
    314322                        } 
    315323                         
    316324                        // this is the level of tiles we'll be loading: 
    317                         _currentZoom = newZoom; 
    318                  
    319                         // this is how big the world is, in tiles: 
    320                         // (same as rounding scale to the nearest power of 2) 
    321                         var numCols:int = Math.pow(2, currentZoom); 
    322                         var numRows:int = numCols; // TODO deal with what happens with non-square projections! 
    323                                          
    324                         // find start and end columns for the visible tiles: 
     325                        _currentTileZoom = newZoom; 
     326                 
     327                        // find start and end columns for the visible tiles, at current tile zoom 
    325328                        // TODO: take account of potential rotation in worldMatrix (ask Tom about this if you need it) 
    326                         var realMinCol:Number = numCols * (-worldMin.x) / (worldMax.x-worldMin.x); 
    327                         var realMaxCol:Number = numCols * (mapWidth-worldMin.x) / (worldMax.x-worldMin.x); 
    328                         var realMinRow:Number = numRows * (-worldMin.y) / (worldMax.y-worldMin.y); 
    329                         var realMaxRow:Number = numRows * (mapHeight-worldMin.y) / (worldMax.y-worldMin.y); 
    330                          
    331                         // round these up or down to pad things out a bit 
    332                         var minCol:int = Math.floor(realMinCol); 
    333                         var maxCol:int = Math.ceil(realMaxCol); 
    334                         var minRow:int = Math.floor(realMinRow); 
    335                         var maxRow:int = Math.ceil(realMaxRow); 
    336                                          
    337                         // optionally pad it out a little bit more 
     329                        var tlC:Coordinate = topLeftCoordinate.zoomTo(currentTileZoom); 
     330                        var brC:Coordinate = bottomRightCoordinate.zoomTo(currentTileZoom); 
     331                         
     332                        // optionally pad it out a little bit more with a tile buffer 
    338333                        // TODO: investigate giving a directional bias to TILE_BUFFER when panning quickly 
    339                        minCol -= tileBuffer; 
    340                         maxCol += tileBuffer; 
    341                         minRow -= tileBuffer; 
    342                         maxRow += tileBuffer;  
     334                       var minCol:int = Math.floor(tlC.column) - tileBuffer; 
     335                        var maxCol:int = Math.ceil(brC.column) + tileBuffer; 
     336                        var minRow:int = Math.floor(tlC.row) - tileBuffer; 
     337                        var maxRow:int = Math.ceil(brC.row) + tileBuffer; 
    343338 
    344339                        // loop over all tiles and find parent or child tiles from cache to compensate for unloaded tiles:                       
    345340                        repopulateVisibleTiles(minCol, maxCol, minRow, maxRow); 
    346341 
    347                         // make absolutlely sure all our newly visible tiles are cached if they're done loading 
    348                         // TODO: should this happen onLoadEnd when there are no URLs left?  
     342                        // move visible tiles to the end of recentlySeen if we're done loading them 
     343                        // the 'least recently seen' tiles will be removed from the tileCache below 
    349344                        for each (var visibleTile:Tile in visibleTiles) { 
    350                                 // if we're done loading this one, add/move it to the end of recently seen: 
    351345                                if (!layersNeeded[visibleTile.name]) { 
    352346                                        var ri:int = recentlySeen.indexOf(visibleTile.name);  
     
    355349                                        } 
    356350                                        recentlySeen.push(visibleTile.name); 
    357                                 }                               
     351                                } 
    358352                        } 
    359353 
     
    377371 
    378372                        // position tiles such that currentZoom is approximately scale 1 
    379                         // and x and y make sense in pixels relative to realMinCol and realMinRow, topleft 
    380                         positionTiles(realMinCol, realMinRow); 
     373                        // and x and y make sense in pixels relative to tlC.column and tlC.row (topleft) 
     374                        positionTiles(tlC.column, tlC.row); 
    381375 
    382376                        // all the visible tiles will be at the end of recentlySeen 
     
    395389                        } 
    396390                         
    397                         // update center position:                       
    398                         centerRow = (realMaxRow+realMinRow)/2; 
    399                         centerColumn = (realMaxCol+realMinCol)/2.0; 
     391                        // update centerRow and centerCol for sorting the tileQueue in processQueue() 
     392                        var center:Coordinate = centerCoordinate.zoomTo(currentTileZoom); 
     393                        centerRow = center.row; 
     394                        centerColumn = center.column; 
    400395 
    401396                        dirty = false; 
     
    420415                                         
    421416                                        // create a string key for this tile 
    422                                         var key:String = tileKey(col, row, currentZoom); 
     417                                        var key:String = tileKey(col, row, currentTileZoom); 
    423418                                         
    424419                                        // see if we already have this tile 
     
    429424                                                tile = tileCache.getTile(key); 
    430425                                                if (!tile) { 
    431                                                         tile = tilePool.getTile(col, row, currentZoom); 
     426                                                        tile = tilePool.getTile(col, row, currentTileZoom); 
    432427                                                        tile.name = key; 
    433428                                                        coord.row = tile.row; 
     
    468463                                                var foundChildren:int = 0; 
    469464         
    470                                                 if (currentZoom > previousZoom) { 
     465                                                if (currentTileZoom > previousTileZoom) { 
    471466                                                         
    472467                                                        // if it still doesn't have enough images yet, or it's fading in, try a double size parent instead 
    473                                                         if (maxParentSearch > 0 && currentZoom > minZoom) { 
    474                                                                 if (ensureVisible(parentKey(col, row, currentZoom, currentZoom-1))) { 
     468                                                        if (maxParentSearch > 0 && currentTileZoom > minZoom) { 
     469                                                                if (ensureVisible(parentKey(col, row, currentTileZoom, currentTileZoom-1))) { 
    475470                                                                        foundParent = true; 
    476471                                                                } 
     
    484479                                                         
    485480                                                        // if it doesn't have an image yet, see if we can make it from smaller images 
    486                                                         if (!foundParent && maxChildSearch > 0 && currentZoom < maxZoom) { 
    487                                                                 for (var czoom:int = currentZoom+1; czoom <= Math.min(maxZoom, currentZoom+maxChildSearch); czoom++) { 
    488                                                                         var ckeys:Array = childKeys(col, row, currentZoom, czoom); 
     481                                                        if (!foundParent && maxChildSearch > 0 && currentTileZoom < maxZoom) { 
     482                                                                for (var czoom:int = currentTileZoom+1; czoom <= Math.min(maxZoom, currentTileZoom+maxChildSearch); czoom++) { 
     483                                                                        var ckeys:Array = childKeys(col, row, currentTileZoom, czoom); 
    489484                                                                        for each (var ckey:String in ckeys) { 
    490485                                                                                if (ensureVisible(ckey)) { 
     
    499494                                                } 
    500495         
    501                                                 var startZoomSearch:int = currentZoom - 1; 
     496                                                var startZoomSearch:int = currentTileZoom - 1; 
    502497                                                 
    503                                                 if (currentZoom > previousZoom) { 
     498                                                if (currentTileZoom > previousTileZoom) { 
    504499                                                        // we already looked for parent level 1, and didn't find it, so: 
    505500                                                        startZoomSearch -= 1; 
    506501                                                } 
    507502                                                 
    508                                                 var endZoomSearch:int = Math.max(minZoom, currentZoom-maxParentSearch); 
     503                                                var endZoomSearch:int = Math.max(minZoom, currentTileZoom-maxParentSearch); 
    509504         
    510505                                                var stillNeedsAnImage:Boolean = !foundParent && foundChildren < 4;                                       
    511506                                                // if it still doesn't have an image yet, try more parent zooms 
    512                                                 if (stillNeedsAnImage && maxParentSearch > 1 && currentZoom > minZoom) { 
     507                                                if (stillNeedsAnImage && maxParentSearch > 1 && currentTileZoom > minZoom) { 
    513508                                                        for (var pzoom:int = startZoomSearch; pzoom >= endZoomSearch; pzoom--) { 
    514                                                                 if (ensureVisible(parentKey(col, row, currentZoom, pzoom))) {                                                          
     509                                                                if (ensureVisible(parentKey(col, row, currentTileZoom, pzoom))) {                                                              
    515510                                                                        stillNeedsAnImage = false; 
    516511                                                                        break; 
     
    537532 
    538533                        // for fixing positions when we're between zoom levels: 
    539                         var positionScaleCompensation:Number = Math.pow(2, zoomLevel-currentZoom); 
     534                        var positionScaleCompensation:Number = Math.pow(2, zoomLevel-currentTileZoom); 
     535                         
     536                        // for positioning tile according to current transform, based on current tile zoom 
     537                        var scaleFactors:Array = new Array(maxZoom+1); 
     538                        // scales to compensate for zoom differences between current grid zoom level                             
     539                        var tileScales:Array = new Array(maxZoom+1); 
     540                        for (var z:int = 0; z <= maxZoom; z++) { 
     541                                scaleFactors[z] = Math.pow(2.0, currentTileZoom-z) 
     542                                tileScales[z] = Math.pow(2, zoomLevel-z); 
     543                        } 
    540544                         
    541545                        // apply the sorted depths, position all the tiles and also keep recentlySeen updated: 
     
    545549                                well.setChildIndex(tile, well.numChildren-1); 
    546550 
    547                                 // scale to compensate for zoom differences                              
    548                                 var tileScale:Number = Math.pow(2, zoomLevel-tile.zoom); 
    549                                 tileScale = Math.ceil(tileScale * tileWidth) / tileWidth; // round up to the nearest pixel 
    550                                 tile.scaleX = tile.scaleY = tileScale; 
    551  
    552                                 // position tile according to current transform 
    553                                 var scaleFactor:Number = Math.pow(2.0, currentZoom-tile.zoom); 
    554                                 var positionCol:Number = (scaleFactor*tile.column) - realMinCol; 
    555                                 var positionRow:Number = (scaleFactor*tile.row) - realMinRow; 
    556                                 tile.x = Math.floor(positionCol*tileWidth*positionScaleCompensation); 
    557                                 tile.y = Math.floor(positionRow*tileHeight*positionScaleCompensation); 
     551                                var positionCol:Number = (scaleFactors[tile.zoom]*tile.column) - realMinCol; 
     552                                var positionRow:Number = (scaleFactors[tile.zoom]*tile.row) - realMinRow; 
     553 
     554                                // round up to the nearest pixel to avoid seams between zoom levels  
     555                                tile.scaleX = tile.scaleY = Math.ceil(tileScales[tile.zoom] * tileWidth) / tileWidth;; 
     556 
     557                                if (!zooming) { 
     558                                        // this also helps the rare seams not fixed by rounding the tile scale,  
     559                                        // but makes slow zooming uglier:  
     560                                        tile.x = Math.floor(positionCol*tileWidth*positionScaleCompensation); 
     561                                        tile.y = Math.floor(positionRow*tileHeight*positionScaleCompensation); 
     562                                } 
     563                                else { 
     564                                        tile.x = positionCol*tileWidth*positionScaleCompensation; 
     565                                        tile.y = positionRow*tileHeight*positionScaleCompensation; 
     566                                } 
     567                                 
    558568                        }                        
    559569                } 
     
    561571                private function processQueue():void 
    562572                { 
    563                         // prepare the queue 
    564573                        if (openRequests.length < maxOpenRequests && tileQueue.length > 0) { 
    565574 
     
    567576                                var removedTiles:Array = tileQueue.retainAll(visibleTiles); 
    568577                                 
     578                                // keep layersNeeded tidy: 
    569579                                for each (var removedTile:Tile in removedTiles) { 
    570580                                        delete layersNeeded[removedTile.name]; 
     
    576586         
    577587                                // sort queue by distance from 'center' 
    578                                 tileQueue.sortTiles(centerDistanceCompare);                             
    579                         } 
    580                          
    581                         // process the queue 
    582                         while (openRequests.length < maxOpenRequests && tileQueue.length > 0) { 
    583                                 var tile:Tile = tileQueue.shift(); 
    584                                 // if it's still on the stage: 
    585                                 if (tile.parent) { 
    586                                         loadNextURLForTile(tile); 
    587                                 } 
    588                         } 
    589                          
     588                                tileQueue.sortTiles(centerDistanceCompare); 
     589                                                                
     590                               // process the queue 
     591                               while (openRequests.length < maxOpenRequests && tileQueue.length > 0) { 
     592                                       var tile:Tile = tileQueue.shift(); 
     593                                       // if it's still on the stage: 
     594                                       if (tile.parent) { 
     595                                               loadNextURLForTile(tile); 
     596                                        } 
     597                                } 
     598                        } 
     599 
    590600                        // you might want to wait for tiles to load before displaying other data, interface elements, etc. 
    591601                        // these events take care of that for you... 
     
    595605                        else if (previousOpenRequests > 0 && openRequests.length == 0) { 
    596606                                dispatchEvent(new MapEvent(MapEvent.ALL_TILES_LOADED)); 
    597                         } 
     607                                trace("requesting redraw to take parent and child tiles off the stage if we haven't already"); 
     608                                dirty = true; 
     609                        } 
     610                         
    598611                        previousOpenRequests = openRequests.length; 
    599                          
    600612                } 
    601613 
     
    619631                        } 
    620632                        else if (urls && urls.length == 0) { 
    621                                 if (tile.zoom == currentZoom) { 
     633                                if (tile.zoom == currentTileZoom) { 
    622634                                        tile.show(); 
    623635                                } 
     
    633645                private function centerDistanceCompare(t1:Tile, t2:Tile):int 
    634646                { 
    635                         if (t1.zoom == t2.zoom && t1.zoom == currentZoom && t2.zoom == currentZoom) { 
     647                        if (t1.zoom == t2.zoom && t1.zoom == currentTileZoom && t2.zoom == currentTileZoom) { 
    636648                                var d1:int = Math.pow(t1.row+0.5-centerRow,2) + Math.pow(t1.column+0.5-centerColumn,2);  
    637649                                var d2:int = Math.pow(t2.row+0.5-centerRow,2) + Math.pow(t2.column+0.5-centerColumn,2);  
    638650                                return d1 < d2 ? -1 : d1 > d2 ? 1 : 0;  
    639651                        } 
    640                         return Math.abs(t1.zoom-currentZoom) < Math.abs(t2.zoom-currentZoom) ? -1 : 1; 
     652                        return Math.abs(t1.zoom-currentTileZoom) < Math.abs(t2.zoom-currentTileZoom) ? -1 : 1; 
    641653                } 
    642654                 
     
    644656                private function distanceFromCurrentZoomCompare(t1:Tile, t2:Tile):int 
    645657                { 
    646                         var d1:int = Math.abs(t1.zoom-currentZoom); 
    647                         var d2:int = Math.abs(t2.zoom-currentZoom); 
     658                        var d1:int = Math.abs(t1.zoom-currentTileZoom); 
     659                        var d2:int = Math.abs(t2.zoom-currentTileZoom); 
    648660                        return d1 < d2 ? -1 : d1 > d2 ? 1 : 0;  
    649661                } 
     
    726738                                                delete layersNeeded[tile.name]; 
    727739                                                tile.paintError(tileWidth, tileHeight); 
    728                                                 if (tile.zoom == currentZoom) { 
     740                                                if (tile.zoom == currentTileZoom) { 
    729741                                                        tile.show(); 
    730742                                                } 
     
    803815 
    804816                /** read-only, this is the level of tiles we'll be loading first */ 
    805                 public function get currentZoom():Number 
    806                 { 
    807                         return _currentZoom; 
     817                public function get currentTileZoom():Number 
     818                { 
     819                        return _currentTileZoom; 
    808820                } 
    809821 
     
    827839                } 
    828840                                                 
    829                 // for backward compatibility: 
    830                  
    831                 public function centerCoordinate():Coordinate 
    832                 { 
    833                         var c:Point = invertedMatrix.transformPoint(new Point(mapWidth/2, mapHeight/2)); 
    834                         return new Coordinate(c.y, c.x, zoomLevel);                      
     841                public function get centerCoordinate():Coordinate 
     842                { 
     843                        if (!_centerCoordinate) { 
     844                                var c:Point = invertedMatrix.transformPoint(new Point(mapWidth/2, mapHeight/2)); 
     845                                _centerCoordinate = new Coordinate(c.y, c.x, zoomLevel); 
     846                        }  
     847                        return _centerCoordinate;                        
    835848                } 
    836849                 
     
    917930                } 
    918931 
    919                 public function resetTiles(coord:Coordinate, point:Point):void 
     932                public function resetTiles(coord:Coordinate):void 
    920933                { 
    921934                        var sc:Number = Math.pow(2, coord.zoom); 
     
    924937                        worldMatrix.scale(sc, sc); 
    925938                        worldMatrix.translate(mapWidth/2, mapHeight/2 ); 
    926                         worldMatrix.translate(point.x, point.y); 
    927939                        worldMatrix.translate(-tileWidth*coord.column, -tileHeight*coord.row); 
    928940 
     
    11221134                                _invertedMatrix = null; 
    11231135                                _topLeftCoordinate = null; 
    1124                                 _bottomRightCoordinate = null;                           
     1136                                _bottomRightCoordinate = null; 
     1137                                _centerCoordinate = null;                                
    11251138                        } 
    11261139 
     
    11371150                                _topLeftCoordinate = null; 
    11381151                                _bottomRightCoordinate = null;                   
     1152                                _centerCoordinate = null;                                
    11391153                        } 
    11401154                } 
     
    12861300} 
    12871301 
     1302/** the alreadySeen Dictionary here will contain up to grid.maxTilesToKeep Tiles */ 
    12881303class TileCache 
    12891304{ 
     
    13461361} 
    13471362 
     1363/**  
     1364 *  This post http://lab.polygonal.de/2008/06/18/using-object-pools/ 
     1365 *  suggests that using Object pools, especially for complex classes like Sprite 
     1366 *  is a lot faster than calling new Object().  The suggested implementation 
     1367 *  uses a linked list, but to get started with it here I'm using an Array.   
     1368 *   
     1369 *  If anyone wants to try it with a linked list and compare the times, 
     1370 *  it seems like it could be worth it :) 
     1371 */  
    13481372class TilePool  
    13491373{ 
     1374        protected static const MIN_POOL_SIZE:int = 128; 
     1375        protected static const MAX_NEW_TILES:int = 256; 
     1376         
    13501377        protected var pool:Array = []; 
    13511378        protected var tileClass:Class; 
     
    13641391        public function getTile(column:int, row:int, zoom:int):Tile 
    13651392        { 
    1366         if (pool.length > 0) { 
    1367                 trace("reusing a tile"); 
    1368                 var tile:Tile = pool.shift() as Tile; 
    1369                 tile.init(column, row, zoom); 
    1370                 return tile; 
     1393        if (pool.length < MIN_POOL_SIZE) { 
     1394                while (pool.length < MAX_NEW_TILES) { 
     1395                        pool.push(new tileClass(0,0,0)); 
     1396                } 
    13711397        }                                                
    1372                 trace("creating a tile"); 
    1373         return new tileClass(column, row, zoom) as Tile; 
     1398                var tile:Tile = pool.shift() as Tile; 
     1399                tile.init(column, row, zoom); 
     1400                return tile; 
    13741401        } 
    13751402 
  • branches/tom-tweenlite/lib/com/modestmaps/extras/ZoomSlider.as

    r613 r622  
    1010    import flash.filters.BitmapFilterType; 
    1111    import flash.filters.DropShadowFilter; 
     12    import flash.geom.Point; 
    1213    import flash.geom.Rectangle; 
    1314     
    1415    import gs.TweenLite;     
    1516 
     17        /** This is an example of a slider that modifies the zoom level of the given map. 
     18         *  
     19         *  It is provided mainly for ModestMapsSample.as and to test the arbitrary  
     20         *  zoom level functionality, but feel free to use it if you like yellow bevels. */  
    1621    public class ZoomSlider extends Sprite 
    1722    { 
     
    2227 
    2328                private var dragging:Boolean = false; 
     29                private var trackHeight:Number; 
    2430 
    25                 private var HEIGHT:Number = 100; 
     31                private static const DEFAULT_HEIGHT:Number = 100; 
    2632                 
    27         public function ZoomSlider(map:Map
     33        public function ZoomSlider(map:Map, trackHeight:Number=DEFAULT_HEIGHT
    2834        { 
    2935            this.map = map; 
     36            this.trackHeight = trackHeight; 
    3037             
    3138            map.addEventListener(MapEvent.EXTENT_CHANGED, update); 
     
    3946                        track = new Sprite(); 
    4047                        track.filters = [ new BevelFilter(4, 45, 0xffffff, 0.2, 0x000000, 0.2, 4, 4, 1, 1, BitmapFilterType.INNER, false) ]; 
    41                         track.mouseEnabled = false; 
     48                        track.addEventListener(MouseEvent.CLICK, onTrackClick); 
     49                        track.buttonMode = track.useHandCursor = true; 
    4250                        track.graphics.lineStyle(5, 0xd9c588); 
    4351                        track.graphics.moveTo(0, 0); 
    44                         track.graphics.lineTo(0, HEIGHT); 
     52                        track.graphics.lineTo(0, trackHeight); 
    4553                        track.x = 5; 
    4654                        addChild(track); 
     
    5967                        update(); 
    6068        } 
     69 
     70                private function onTrackClick(event:MouseEvent):void 
     71                { 
     72                        var p:Point = globalToLocal(new Point(event.stageX, event.stageY)); 
     73                        thumb.y = p.y; 
     74                        map.grid.zoomLevel = Math.round(map.grid.minZoom + (map.grid.maxZoom - map.grid.minZoom) * proportion); 
     75                } 
    6176         
    6277                private function onThumbMouse(event:Event):void 
    6378                { 
    6479                        if (event.type == MouseEvent.MOUSE_MOVE) { 
    65                                 proportion = thumb.y / HEIGHT
     80                                proportion = thumb.y / trackHeight
    6681                        } 
    6782                        else if (event.type == MouseEvent.MOUSE_DOWN) { 
    68                                 thumb.startDrag(false, new Rectangle(thumb.x, 0, 0, HEIGHT)); 
     83                                thumb.startDrag(false, new Rectangle(thumb.x, 0, 0, trackHeight)); 
    6984                                dragging = true; 
    7085                                stage.addEventListener(MouseEvent.MOUSE_UP, onThumbMouse); 
     
    95110                public function get proportion():Number 
    96111                { 
    97                         return thumb.y / HEIGHT
     112                        return thumb.y / trackHeight
    98113                } 
    99114         
     
    101116                { 
    102117                        if (!dragging) { 
    103                                 thumb.y = prop * HEIGHT
     118                                thumb.y = prop * trackHeight
    104119                        } 
    105120                        else { 
  • branches/tom-tweenlite/lib/com/modestmaps/Map.as

    r621 r622  
    3333         
    3434        import flash.display.DisplayObject; 
    35         import flash.display.Loader; 
    3635        import flash.display.Sprite; 
    3736        import flash.events.Event; 
     
    180179            { 
    181180                onExtentChanging(); 
    182                 var position:MapPosition = extentPosition(extent); 
    183181                // tell grid what the rock is cooking 
    184                 grid.resetTiles(position.coord, position.point); 
     182                grid.resetTiles(locationsCoordinate( [ extent.northWest, extent.southEast ] )); 
    185183                onExtentChanged(); 
    186184            requestCopyrightUpdate(); 
     
    206204                        onExtentChanging(); 
    207205                        zoom = Math.min(Math.max(zoom, grid.minZoom), grid.maxZoom); 
    208                 var center:MapPosition = coordinatePosition(mapProvider.locationCoordinate(location).zoomTo(zoom)); 
    209206                // tell grid what the rock is cooking 
    210                 grid.resetTiles(center.coord, center.point); 
     207                grid.resetTiles(mapProvider.locationCoordinate(location).zoomTo(zoom)); 
    211208                onExtentChanged(); 
    212209                requestCopyrightUpdate(); 
     
    231228                        else { // else hard reset 
    232229                                onExtentChanging(); 
    233                                 var center:MapPosition = coordinatePosition(grid.centerCoordinate().zoomTo(zoom)); 
    234230                                // tell grid what the rock is cooking 
    235                                 grid.resetTiles(center.coord, center.point); 
     231                                grid.resetTiles(grid.centerCoordinate.zoomTo(zoom)); 
    236232                                onExtentChanged(); 
    237233                                requestCopyrightUpdate(); 
     
    239235        } 
    240236                 
    241            /** 
    242             * Based on a coordinate, determine appropriate starting tile and position, 
    243             * and return a two-element object with a coord and a point. 
    244             */ 
    245             public function coordinatePosition(centerCoord:Coordinate):MapPosition 
    246             { 
    247                 // initial tile coordinate 
    248                 var initTileCoord:Coordinate = new Coordinate( Math.floor(centerCoord.row), 
    249                                                            Math.floor(centerCoord.column), 
    250                                                            Math.floor(centerCoord.zoom) ); 
    251          
    252                 // initial tile position, assuming centered tile well in grid 
    253                 var initX:Number = (initTileCoord.column - centerCoord.column) * mapProvider.tileWidth; 
    254                 var initY:Number = (initTileCoord.row - centerCoord.row) * mapProvider.tileHeight; 
    255                 var initPoint:Point = new Point(Math.round(initX), Math.round(initY)); 
    256                  
    257                 return new MapPosition(initTileCoord, initPoint); 
    258             } 
    259  
    260  
    261                 public function locationsPosition(locations:Array):MapPosition 
     237                public function locationsCoordinate(locations:Array):Coordinate 
    262238                { 
    263239                var TL:Coordinate = mapProvider.locationCoordinate(locations[0]); 
     
    306282                var centerCoord:Coordinate = (new Coordinate(centerRow, centerColumn, centerZoom)).zoomTo(initZoom); 
    307283                 
    308                 return coordinatePosition(centerCoord)
     284                return centerCoord
    309285                } 
    310  
    311            /* 
    312             * Based on an array of locations, determine appropriate map bounds 
    313             * in terms of tile grid, and return a two-element object with a coord 
    314             * and a point from calculateMapCenter(). 
    315             */ 
    316             public function ex