OpenLayers OpenLayers

Changeset 6371

Show
Ignore:
Timestamp:
02/25/08 22:11:55 (11 months ago)
Author:
crschmidt
Message:

Add early version of transition patch, from #933

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • sandbox/crschmidt/demo/lib/OpenLayers/Layer.js

    r6149 r6371  
    249249    wrapDateLine: false, 
    250250     
     251    /** 
     252     * APIProperty: transitionEffect 
     253     * {String} The transition effect to use when the map is panned or 
     254     * zoomed.  There is currently two supported values: 
     255     * null - no transition effect (the default). 
     256     * keep - Keep tiles around. This uses double-buffering: this 
     257     *    type of transition effect is only useful for singleTile layers, 
     258     *    where the tile will be kept in place on drag. 
     259     * resize - existing tiles are resized on zoom to provide a visual 
     260     *   effect of the zoom having taken place immediately.  As the 
     261     *   new tiles become available, they are drawn over top of the 
     262     *    resized tiles. 
     263     */ 
     264    transitionEffect: null, 
    251265     
    252266    /** 
  • sandbox/crschmidt/demo/lib/OpenLayers/Tile.js

    r6313 r6371  
    8181    isLoading: false, 
    8282     
     83    /** 
     84     * Property: isBackBuffer 
     85     * {Boolean} Is this tile a back buffer tile? 
     86     */ 
     87    isBackBuffer: false, 
     88     
     89    /** 
     90     * Property: isFirstDraw 
     91     * {Boolean} Is this the first time the tile is being drawn? 
     92     * This is used to force resetBackBuffer to synchronize 
     93     * the backBufferTile with the foreground tile the first time 
     94     * the foreground tile loads so that if the user zooms 
     95     * before the layer has fully loaded, the backBufferTile for 
     96     * tiles that have been loaded can be used. 
     97     */ 
     98    isFirstDraw: true, 
     99         
     100    /** 
     101     * Property: backBufferTile 
     102     * {<OpenLayers.Tile>} A clone of the tile used to create transition 
     103     * effects when the tile is moved or changes resolution. 
     104     */ 
     105    backBufferTile: null, 
     106         
    83107    /** TBD 3.0 -- remove 'url' from the list of parameters to the constructor. 
    84108     *             there is no need for the base tile class to have a url. 
     
    112136     */ 
    113137    destroy:function() { 
     138        if (this.layer.transitionEffect) { 
     139            this.layer.events.unregister("loadend", this, this.resetBackBuffer); 
     140            this.events.unregister('loadend', this, this.resetBackBuffer);             
     141        } else { 
     142            this.events.unregister('loadend', this, this.showTile); 
     143        } 
    114144        this.layer  = null; 
    115145        this.bounds = null; 
     
    119149        this.events.destroy(); 
    120150        this.events = null; 
     151         
     152        /* clean up the backBufferTile if it exists */ 
     153        if (this.backBufferTile) { 
     154            this.backBufferTile.destroy(); 
     155            this.backBufferTile = null; 
     156        } 
    121157    }, 
    122158     
     
    158194    draw: function() { 
    159195         
    160         //clear tile's contents and mark as not drawn 
    161         this.clear(); 
    162          
    163196        var maxExtent = this.layer.maxExtent; 
    164197        var withinMaxExtent = (maxExtent && 
     
    167200        // The only case where we *wouldn't* want to draw the tile is if the  
    168201        // tile is outside its layer's maxExtent. 
    169         return (withinMaxExtent || this.layer.displayOutsideMaxExtent); 
     202        var drawTile = (withinMaxExtent || this.layer.displayOutsideMaxExtent); 
     203         
     204        if (this.layer.transitionEffect != null) { 
     205            if (drawTile) { 
     206                //we use a clone of this tile to create a double buffer for visual 
     207                //continuity.  The backBufferTile is used to create transition 
     208                //effects while the tile in the grid is repositioned and redrawn 
     209                if (!this.backBufferTile) { 
     210                    this.backBufferTile = this.clone(); 
     211                    this.backBufferTile.hide(); 
     212                    // this is important.  It allows the backBuffer to place itself 
     213                    // appropriately in the DOM.  The Image subclass needs to put 
     214                    // the backBufferTile behind the main tile so the tiles can 
     215                    // load over top and display as soon as they are loaded. 
     216                    this.backBufferTile.isBackBuffer = true; 
     217                     
     218                    // potentially end any transition effects when the tile loads 
     219                    this.events.register('loadend', this, this.resetBackBuffer); 
     220                     
     221                    // clear transition back buffer tile only after all tiles in 
     222                    // this layer have loaded to avoid visual glitches 
     223                    this.layer.events.register("loadend", this, this.resetBackBuffer); 
     224                } 
     225                // run any transition effects 
     226                this.startTransition(); 
     227            } else { 
     228                // if we aren't going to draw the tile, then the backBuffer should 
     229                // be hidden too! 
     230                if (this.backBufferTile) { 
     231                    this.backBufferTile.clear(); 
     232                } 
     233            } 
     234        } else { 
     235            if (this.isFirstDraw) { 
     236                this.events.register('loadend', this, this.showTile); 
     237                this.isFirstDraw = false; 
     238            }    
     239        }     
     240        this.shouldDraw = drawTile; 
     241         
     242        //clear tile's contents and mark as not drawn 
     243        this.clear(); 
     244         
     245        return drawTile; 
    170246    }, 
    171247     
     
    238314        return bounds; 
    239315    },         
    240  
     316     
     317    /**  
     318     * Method: startTransition 
     319     * 
     320     * prepare the tile for a transition effect.  To be 
     321     * implemented by subclasses. 
     322     */ 
     323    startTransition: function() {}, 
     324     
     325    /**  
     326     * Method: resetBackBuffer 
     327     * 
     328     * triggered by two different events, layer loadend, and tile loadend. 
     329     * In any of these cases, we check to see if we can hide the  
     330     * backBufferTile yet and update its parameters to match the  
     331     * foreground tile.  Basic logic: 
     332     * 
     333     * - If the backBufferTile hasn't been drawn yet, reset it 
     334     * - If layer is still loading, show foreground tile but don't hide 
     335     *   the backBufferTile yet 
     336     * - If layer is done loading, reset backBuffer tile and show  
     337     *   foreground tile 
     338     */ 
     339    resetBackBuffer: function(args) { 
     340        if (this.backBufferTile &&  
     341            (this.isFirstDraw || !this.layer.numLoadingTiles)) { 
     342            this.backBufferTile.hide(); 
     343            this.isFirstDraw = false; 
     344            // check to see if the backBufferTile is within the max extents 
     345            // before rendering it  
     346            var maxExtent = this.layer.maxExtent; 
     347            var withinMaxExtent = (maxExtent && 
     348                                   this.bounds.intersectsBounds(maxExtent, false)); 
     349            if (withinMaxExtent) { 
     350                this.backBufferTile.position = this.position.clone(); 
     351                this.backBufferTile.bounds = this.bounds.clone(); 
     352                this.backBufferTile.size = this.size.clone(); 
     353                this.backBufferTile.resolution = this.layer.getResolution(); 
     354                this.backBufferTile.renderTile(); 
     355            } 
     356        } 
     357        this.showTile(); 
     358    }, 
     359         
     360    /**  
     361     * Method: showTile 
     362     * 
     363     * show the tile only if it should be drawn. 
     364     */ 
     365    showTile: function() {  
     366        if (this.shouldDraw) { 
     367            this.show(); 
     368        } 
     369    }, 
     370     
     371    /**  
     372     * Method: show 
     373     * 
     374     * show the tile.  To be implemented by subclasses. 
     375     */ 
     376    show: function() { }, 
     377     
     378    /**  
     379     * Method: hide 
     380     * 
     381     * hide the tile.  To be implemented by subclasses. 
     382     */ 
     383    hide: function() { }, 
     384     
    241385    CLASS_NAME: "OpenLayers.Tile" 
    242386}); 
  • sandbox/crschmidt/demo/lib/OpenLayers/Tile/Image.js

    r6068 r6371  
    147147        } 
    148148         
     149        return this.renderTile(); 
     150    }, 
     151     
     152    /** 
     153     * Method: renderTile 
     154     * 
     155     * internal function to actually initialize the image tile, 
     156     * position it correctly, and set its url 
     157     */ 
     158    renderTile: function() { 
    149159        if (this.imgDiv == null) { 
    150160            this.initImgDiv(); 
     
    163173                    null, null, imageSize, this.url); 
    164174        } else { 
    165             this.imgDiv.src = this.url; 
    166175            OpenLayers.Util.modifyDOMElement(this.imgDiv, 
    167176                    null, null, imageSize) ; 
     177            this.imgDiv.src = this.url; 
    168178        } 
    169179        return true; 
     
    177187    clear: function() { 
    178188        if(this.imgDiv) { 
    179             this.imgDiv.style.display = "none"
     189            this.hide()
    180190            if (OpenLayers.Tile.Image.useBlankTile) {  
    181191                this.imgDiv.src = OpenLayers.Util.getImagesLocation() + "blank.gif"; 
     
    224234            OpenLayers.Function.bind(this.checkImgURL, this) ); 
    225235        */ 
     236        this.frame.style.zIndex = this.isBackBuffer ? 0 : 1; 
    226237        this.frame.appendChild(this.imgDiv);  
    227238        this.layer.div.appendChild(this.frame);  
     
    301312            var loaded = this.layerAlphaHack ? this.imgDiv.firstChild.src : this.imgDiv.src; 
    302313            if (!OpenLayers.Util.isEquivalentUrl(loaded, this.url)) { 
    303                 this.imgDiv.style.display = "none"; 
    304             } 
    305         } 
    306     }, 
    307  
     314                this.hide(); 
     315            } 
     316        } 
     317    }, 
     318     
     319    /** 
     320     * Method: startTransition 
     321     * 
     322     * This method is invoked on tiles that are backBuffers for tiles in the 
     323     * grid.  The grid tile is about to be cleared and a new tile source 
     324     * loaded.  This is where the transition effect needs to be started 
     325     * to provide visual continuity. 
     326     */ 
     327    startTransition: function() { 
     328        // backBufferTile has to be valid and ready to use 
     329        if (!this.backBufferTile || !this.backBufferTile.imgDiv) { 
     330            return; 
     331        } 
     332 
     333        // show the backBufferTile and hide this tile 
     334        this.hide(); 
     335 
     336        // calculate the ratio of change between the current resolution of the 
     337        // backBufferTile and the layer.  If several animations happen in a 
     338        // row, then the backBufferTile will scale itself appropriately for 
     339        // each request. 
     340        var ratio = 1; 
     341        if (this.backBufferTile.resolution) { 
     342            ratio = this.backBufferTile.resolution / this.layer.getResolution() ; 
     343        } 
     344         
     345        // if the ratio is not 1 (i.e. we are zooming), then we might be  
     346        // resizing the backBuffer tile ... 
     347        if (ratio != 1) { 
     348            if (this.layer.transitionEffect == 'resize') { 
     349                // In this case, we can just immediately resize the  
     350                // backBufferTile. 
     351                var upperLeft =  
     352                    new OpenLayers.LonLat(this.backBufferTile.bounds.left,  
     353                                          this.backBufferTile.bounds.top); 
     354                var size =  
     355                    new OpenLayers.Size(this.backBufferTile.size.w * ratio,  
     356                                        this.backBufferTile.size.h * ratio); 
     357 
     358                var px = this.layer.map.getLayerPxFromLonLat(upperLeft); 
     359                OpenLayers.Util.modifyDOMElement(this.backBufferTile.frame,  
     360                                                 null, px, size);    
     361                var imageSize = this.backBufferTile.size.clone(); 
     362                imageSize = new OpenLayers.Size(imageSize.w * ratio,  
     363                                                imageSize.h * ratio); 
     364 
     365                OpenLayers.Util.modifyDOMElement(this.backBufferTile.imgDiv, 
     366                                                 null, null, imageSize) ; 
     367 
     368                this.backBufferTile.show(); 
     369            } 
     370        } else { 
     371            // default effect is just to leave the existing tile 
     372            // until the new one loads if this is a singleTile and 
     373            // there was no change in resolution.  Otherwise we 
     374            // don't bother to show the backBufferTile at all 
     375            if (this.layer.singleTile && ratio == 1) { 
     376                this.backBufferTile.show(); 
     377            } else { 
     378                this.backBufferTile.hide(); 
     379            } 
     380        } 
     381    }, 
     382     
     383    /**  
     384     * Method: show 
     385     * 
     386     * show the tile by showing its frame. 
     387     */ 
     388    show: function() { 
     389        this.frame.style.display = ''; 
     390    }, 
     391     
     392    /**  
     393     * Method: hide 
     394     * 
     395     * hide the tile by hiding its frame. 
     396     */ 
     397    hide: function() { 
     398        this.frame.style.display = 'none'; 
     399    }, 
     400     
    308401    CLASS_NAME: "OpenLayers.Tile.Image" 
    309402  }