OpenLayers OpenLayers

Ticket #933: resize_transition.patch

File resize_transition.patch, 11.8 kB (added by crschmidt, 1 year ago)

fewer bits, more clean

  • lib/OpenLayers/Tile/Image.js

    old new  
    146146            this.events.triggerEvent("loadstart"); 
    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(); 
    151161        } 
     
    162172            OpenLayers.Util.modifyAlphaImageDiv(this.imgDiv, 
    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; 
    170180    }, 
     
    176186     */ 
    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"; 
    182192            }     
     
    223233        OpenLayers.Event.observe( this.imgDiv, "load", 
    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);  
    228239 
     
    300311        if (this.layer) { 
    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"
     314                this.hide()
    304315            } 
    305316        } 
    306317    }, 
     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        } 
    307332 
     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  } 
    310403); 
  • lib/OpenLayers/Tile.js

    old new  
    8080     */ 
    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. 
    85109     *  
     
    111135     * Nullify references to prevent circular references and memory leaks. 
    112136     */ 
    113137    destroy:function() { 
     138        this.layer.events.unregister("loadend", this, this.resetBackBuffer); 
     139        this.events.unregister('loadend', this, this.resetBackBuffer); 
    114140        this.layer  = null; 
    115141        this.bounds = null; 
    116142        this.size = null; 
     
    118144         
    119145        this.events.destroy(); 
    120146        this.events = null; 
     147         
     148        /* clean up the backBufferTile if it exists */ 
     149        if (this.backBufferTile) { 
     150            this.backBufferTile.destroy(); 
     151            this.backBufferTile = null; 
     152        } 
    121153    }, 
    122154     
    123155    /** 
     
    157189     */ 
    158190    draw: function() { 
    159191         
    160         //clear tile's contents and mark as not drawn 
    161         this.clear(); 
    162          
    163192        var maxExtent = this.layer.maxExtent; 
    164193        var withinMaxExtent = (maxExtent && 
    165194                               this.bounds.intersectsBounds(maxExtent, false)); 
    166195  
    167196        // The only case where we *wouldn't* want to draw the tile is if the  
    168197        // tile is outside its layer's maxExtent. 
    169         return (withinMaxExtent || this.layer.displayOutsideMaxExtent); 
     198        var drawTile = (withinMaxExtent || this.layer.displayOutsideMaxExtent); 
     199         
     200        if (drawTile) { 
     201            //we use a clone of this tile to create a double buffer for visual 
     202            //continuity.  The backBufferTile is used to create transition 
     203            //effects while the tile in the grid is repositioned and redrawn 
     204            if (!this.backBufferTile) { 
     205                this.backBufferTile = this.clone(); 
     206                this.backBufferTile.hide(); 
     207                // this is important.  It allows the backBuffer to place itself 
     208                // appropriately in the DOM.  The Image subclass needs to put 
     209                // the backBufferTile behind the main tile so the tiles can 
     210                // load over top and display as soon as they are loaded. 
     211                this.backBufferTile.isBackBuffer = true; 
     212                 
     213                // potentially end any transition effects when the tile loads 
     214                this.events.register('loadend', this, this.resetBackBuffer); 
     215                 
     216                // clear transition back buffer tile only after all tiles in 
     217                // this layer have loaded to avoid visual glitches 
     218                this.layer.events.register("loadend", this, this.resetBackBuffer); 
     219            } 
     220            // run any transition effects 
     221            this.startTransition(); 
     222        } else { 
     223            // if we aren't going to draw the tile, then the backBuffer should 
     224            // be hidden too! 
     225            if (this.backBufferTile) { 
     226                this.backBufferTile.clear(); 
     227            } 
     228        } 
     229        this.shouldDraw = drawTile; 
     230         
     231        //clear tile's contents and mark as not drawn 
     232        this.clear(); 
     233         
     234        return drawTile; 
    170235    }, 
    171236     
    172237    /**  
     
    240305                                       topLeft.lat);   
    241306        return bounds; 
    242307    },         
    243  
     308     
     309    /**  
     310     * Method: startTransition 
     311     * 
     312     * prepare the tile for a transition effect.  To be 
     313     * implemented by subclasses. 
     314     */ 
     315    startTransition: function() {}, 
     316     
     317    /**  
     318     * Method: resetBackBuffer 
     319     * 
     320     * triggered by two different events, layer loadend, and tile loadend. 
     321     * In any of these cases, we check to see if we can hide the  
     322     * backBufferTile yet and update its parameters to match the  
     323     * foreground tile.  Basic logic: 
     324     * 
     325     * - If the backBufferTile hasn't been drawn yet, reset it 
     326     * - If layer is still loading, show foreground tile but don't hide 
     327     *   the backBufferTile yet 
     328     * - If layer is done loading, reset backBuffer tile and show  
     329     *   foreground tile 
     330     */ 
     331    resetBackBuffer: function(args) { 
     332        if (this.backBufferTile &&  
     333            (this.isFirstDraw || !this.layer.numLoadingTiles)) { 
     334            this.backBufferTile.hide(); 
     335            this.backBufferTile.position = this.position.clone(); 
     336            this.backBufferTile.bounds = this.bounds.clone(); 
     337            this.backBufferTile.size = this.size.clone(); 
     338            this.backBufferTile.resolution = this.layer.getResolution(); 
     339            this.backBufferTile.renderTile(); 
     340            this.isFirstDraw = false; 
     341        } 
     342        if (this.shouldDraw) { 
     343            this.show(); 
     344        } 
     345    }, 
     346         
     347    /**  
     348     * Method: show 
     349     * 
     350     * show the tile.  To be implemented by subclasses. 
     351     */ 
     352    show: function() { }, 
     353     
     354    /**  
     355     * Method: hide 
     356     * 
     357     * hide the tile.  To be implemented by subclasses. 
     358     */ 
     359    hide: function() { }, 
     360     
    244361    CLASS_NAME: "OpenLayers.Tile" 
    245362}); 
  • lib/OpenLayers/Layer.js

    old new  
    231231     */ 
    232232    wrapDateLine: false, 
    233233     
     234    /** 
     235     * APIProperty: transitionEffect 
     236     * {String} The transition effect to use when the map is panned or 
     237     * zoomed.  There is currently two supported values: 
     238     * null - no transition effect (the default). 
     239     * resize - existing tiles are resized on zoom to provide a visual 
     240     *   effect of the zoom having taken place immediately.  As the 
     241     *   new tiles become available, they are drawn over top of the 
     242     *    resized tiles. 
     243     */ 
     244    transitionEffect: null, 
    234245     
    235246    /** 
    236247     * Constructor: OpenLayers.Layer