Bienvenue sur PostGIS.fr

Bienvenue sur PostGIS.fr , le site de la communauté des utilisateurs francophones de PostGIS.

PostGIS ajoute le support d'objets géographique à la base de données PostgreSQL. En effet, PostGIS "spatialise" le serverur PostgreSQL, ce qui permet de l'utiliser comme une base de données SIG.

Maintenu à jour, en fonction de nos disponibilités et des diverses sorties des outils que nous testons, nous vous proposons l'ensemble de nos travaux publiés en langue française.

source: trunk/workshop-routing-foss4g/web/OpenLayers/lib/OpenLayers/Tile/Image.js @ 81

Revision 76, 21.9 KB checked in by djay, 12 years ago (diff)

Ajout du répertoire web

  • Property svn:executable set to *
Line 
1/* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for
2 * full list of contributors). Published under the Clear BSD license. 
3 * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
4 * full text of the license. */
5
6
7/**
8 * @requires OpenLayers/Tile.js
9 */
10
11/**
12 * Class: OpenLayers.Tile.Image
13 * Instances of OpenLayers.Tile.Image are used to manage the image tiles
14 * used by various layers.  Create a new image tile with the
15 * <OpenLayers.Tile.Image> constructor.
16 *
17 * Inherits from:
18 *  - <OpenLayers.Tile>
19 */
20OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, {
21
22    /**
23     * Property: url
24     * {String} The URL of the image being requested. No default. Filled in by
25     * layer.getURL() function.
26     */
27    url: null,
28   
29    /**
30     * Property: imgDiv
31     * {DOMElement} The div element which wraps the image.
32     */
33    imgDiv: null,
34
35    /**
36     * Property: frame
37     * {DOMElement} The image element is appended to the frame.  Any gutter on
38     * the image will be hidden behind the frame.
39     */ 
40    frame: null, 
41   
42    /**
43     * Property: layerAlphaHack
44     * {Boolean} True if the png alpha hack needs to be applied on the layer's div.
45     */
46    layerAlphaHack: null,
47   
48    /**
49     * Property: isBackBuffer
50     * {Boolean} Is this tile a back buffer tile?
51     */
52    isBackBuffer: false,
53   
54    /**
55     * Property: lastRatio
56     * {Float} Used in transition code only.  This is the previous ratio
57     *     of the back buffer tile resolution to the map resolution.  Compared
58     *     with the current ratio to determine if zooming occurred.
59     */
60    lastRatio: 1,
61
62    /**
63     * Property: isFirstDraw
64     * {Boolean} Is this the first time the tile is being drawn?
65     *     This is used to force resetBackBuffer to synchronize
66     *     the backBufferTile with the foreground tile the first time
67     *     the foreground tile loads so that if the user zooms
68     *     before the layer has fully loaded, the backBufferTile for
69     *     tiles that have been loaded can be used.
70     */
71    isFirstDraw: true,
72       
73    /**
74     * Property: backBufferTile
75     * {<OpenLayers.Tile>} A clone of the tile used to create transition
76     *     effects when the tile is moved or changes resolution.
77     */
78    backBufferTile: null,
79
80    /** TBD 3.0 - reorder the parameters to the init function to remove
81     *             URL. the getUrl() function on the layer gets called on
82     *             each draw(), so no need to specify it here.
83     *
84     * Constructor: OpenLayers.Tile.Image
85     * Constructor for a new <OpenLayers.Tile.Image> instance.
86     *
87     * Parameters:
88     * layer - {<OpenLayers.Layer>} layer that the tile will go in.
89     * position - {<OpenLayers.Pixel>}
90     * bounds - {<OpenLayers.Bounds>}
91     * url - {<String>} Deprecated. Remove me in 3.0.
92     * size - {<OpenLayers.Size>}
93     */   
94    initialize: function(layer, position, bounds, url, size) {
95        OpenLayers.Tile.prototype.initialize.apply(this, arguments);
96
97        this.url = url; //deprecated remove me
98       
99        this.frame = document.createElement('div'); 
100        this.frame.style.overflow = 'hidden'; 
101        this.frame.style.position = 'absolute'; 
102
103        this.layerAlphaHack = this.layer.alpha && OpenLayers.Util.alphaHack();
104    },
105
106    /**
107     * APIMethod: destroy
108     * nullify references to prevent circular references and memory leaks
109     */
110    destroy: function() {
111        if (this.imgDiv != null)  {
112            if (this.layerAlphaHack) {
113                // unregister the "load" handler
114                OpenLayers.Event.stopObservingElement(this.imgDiv.childNodes[0]);               
115            }
116
117            // unregister the "load" and "error" handlers. Only the "error" handler if
118            // this.layerAlphaHack is true.
119            OpenLayers.Event.stopObservingElement(this.imgDiv);
120           
121            if (this.imgDiv.parentNode == this.frame) {
122                this.frame.removeChild(this.imgDiv);
123                this.imgDiv.map = null;
124            }
125            this.imgDiv.urls = null;
126            // abort any currently loading image
127            this.imgDiv.src = OpenLayers.Util.getImagesLocation() + "blank.gif";
128        }
129        this.imgDiv = null;
130        if ((this.frame != null) && (this.frame.parentNode == this.layer.div)) { 
131            this.layer.div.removeChild(this.frame); 
132        }
133        this.frame = null; 
134       
135        /* clean up the backBufferTile if it exists */
136        if (this.backBufferTile) {
137            this.backBufferTile.destroy();
138            this.backBufferTile = null;
139        }
140       
141        this.layer.events.unregister("loadend", this, this.resetBackBuffer);
142       
143        OpenLayers.Tile.prototype.destroy.apply(this, arguments);
144    },
145
146    /**
147     * Method: clone
148     *
149     * Parameters:
150     * obj - {<OpenLayers.Tile.Image>} The tile to be cloned
151     *
152     * Returns:
153     * {<OpenLayers.Tile.Image>} An exact clone of this <OpenLayers.Tile.Image>
154     */
155    clone: function (obj) {
156        if (obj == null) {
157            obj = new OpenLayers.Tile.Image(this.layer, 
158                                            this.position, 
159                                            this.bounds, 
160                                            this.url, 
161                                            this.size);       
162        } 
163       
164        //pick up properties from superclass
165        obj = OpenLayers.Tile.prototype.clone.apply(this, [obj]);
166       
167        //dont want to directly copy the image div
168        obj.imgDiv = null;
169           
170       
171        return obj;
172    },
173   
174    /**
175     * Method: draw
176     * Check that a tile should be drawn, and draw it.
177     *
178     * Returns:
179     * {Boolean} Always returns true.
180     */
181    draw: function() {
182        if (this.layer != this.layer.map.baseLayer && this.layer.reproject) {
183            this.bounds = this.getBoundsFromBaseLayer(this.position);
184        }
185        var drawTile = OpenLayers.Tile.prototype.draw.apply(this, arguments);
186       
187        if ((OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS, this.layer.transitionEffect) != -1) || 
188            this.layer.singleTile) {
189            if (drawTile) {
190                //we use a clone of this tile to create a double buffer for visual
191                //continuity.  The backBufferTile is used to create transition
192                //effects while the tile in the grid is repositioned and redrawn
193                if (!this.backBufferTile) {
194                    this.backBufferTile = this.clone();
195                    this.backBufferTile.hide();
196                    // this is important.  It allows the backBuffer to place itself
197                    // appropriately in the DOM.  The Image subclass needs to put
198                    // the backBufferTile behind the main tile so the tiles can
199                    // load over top and display as soon as they are loaded.
200                    this.backBufferTile.isBackBuffer = true;
201                   
202                    // potentially end any transition effects when the tile loads
203                    this.events.register('loadend', this, this.resetBackBuffer);
204                   
205                    // clear transition back buffer tile only after all tiles in
206                    // this layer have loaded to avoid visual glitches
207                    this.layer.events.register("loadend", this, this.resetBackBuffer);
208                }
209                // run any transition effects
210                this.startTransition();
211            } else {
212                // if we aren't going to draw the tile, then the backBuffer should
213                // be hidden too!
214                if (this.backBufferTile) {
215                    this.backBufferTile.clear();
216                }
217            }
218        } else {
219            if (drawTile && this.isFirstDraw) {
220                this.events.register('loadend', this, this.showTile);
221                this.isFirstDraw = false;
222            }   
223        }   
224       
225        if (!drawTile) {
226            return false;
227        }
228       
229        if (this.isLoading) {
230            //if we're already loading, send 'reload' instead of 'loadstart'.
231            this.events.triggerEvent("reload"); 
232        } else {
233            this.isLoading = true;
234            this.events.triggerEvent("loadstart");
235        }
236       
237        return this.renderTile();
238    },
239   
240    /**
241     * Method: resetBackBuffer
242     * Triggered by two different events, layer loadend, and tile loadend.
243     *     In any of these cases, we check to see if we can hide the
244     *     backBufferTile yet and update its parameters to match the
245     *     foreground tile.
246     *
247     * Basic logic:
248     *  - If the backBufferTile hasn't been drawn yet, reset it
249     *  - If layer is still loading, show foreground tile but don't hide
250     *    the backBufferTile yet
251     *  - If layer is done loading, reset backBuffer tile and show
252     *    foreground tile
253     */
254    resetBackBuffer: function() {
255        this.showTile();
256        if (this.backBufferTile && 
257            (this.isFirstDraw || !this.layer.numLoadingTiles)) {
258            this.isFirstDraw = false;
259            // check to see if the backBufferTile is within the max extents
260            // before rendering it
261            var maxExtent = this.layer.maxExtent;
262            var withinMaxExtent = (maxExtent &&
263                                   this.bounds.intersectsBounds(maxExtent, false));
264            if (withinMaxExtent) {
265                this.backBufferTile.position = this.position;
266                this.backBufferTile.bounds = this.bounds;
267                this.backBufferTile.size = this.size;
268                this.backBufferTile.imageSize = this.layer.getImageSize(this.bounds) || this.size;
269                this.backBufferTile.imageOffset = this.layer.imageOffset;
270                this.backBufferTile.resolution = this.layer.getResolution();
271                this.backBufferTile.renderTile();
272            }
273
274            this.backBufferTile.hide();
275        }
276    },
277   
278    /**
279     * Method: renderTile
280     * Internal function to actually initialize the image tile,
281     *     position it correctly, and set its url.
282     */
283    renderTile: function() {
284        if (this.imgDiv == null) {
285            this.initImgDiv();
286        }
287
288        this.imgDiv.viewRequestID = this.layer.map.viewRequestID;
289       
290        if (this.layer.async) {
291            // Asyncronous image requests call the asynchronous getURL method
292            // on the layer to fetch an image that covers 'this.bounds', in the scope of
293            // 'this', setting the 'url' property of the layer itself, and running
294            // the callback 'positionFrame' when the image request returns.
295            this.layer.getURLasync(this.bounds, this, "url", this.positionImage);
296        } else {
297            // syncronous image requests get the url and position the frame immediately,
298            // and don't wait for an image request to come back.
299         
300            // needed for changing to a different server for onload error
301            if (this.layer.url instanceof Array) {
302                this.imgDiv.urls = this.layer.url.slice();
303            }
304         
305            this.url = this.layer.getURL(this.bounds);
306         
307            // position the frame immediately
308            this.positionImage(); 
309        }
310        return true;
311    },
312
313    /**
314     * Method: positionImage
315     * Using the properties currenty set on the layer, position the tile correctly.
316     * This method is used both by the async and non-async versions of the Tile.Image
317     * code.
318     */
319     positionImage: function() {
320        // if the this layer doesn't exist at the point the image is
321        // returned, do not attempt to use it for size computation
322        if (this.layer === null) {
323            return;
324        }
325        // position the frame
326        OpenLayers.Util.modifyDOMElement(this.frame, 
327                                          null, this.position, this.size);   
328
329        var imageSize = this.layer.getImageSize(this.bounds); 
330        if (this.layerAlphaHack) {
331            OpenLayers.Util.modifyAlphaImageDiv(this.imgDiv,
332                    null, null, imageSize, this.url);
333        } else {
334            OpenLayers.Util.modifyDOMElement(this.imgDiv,
335                    null, null, imageSize) ;
336            this.imgDiv.src = this.url;
337        }
338    },
339
340    /**
341     * Method: clear
342     *  Clear the tile of any bounds/position-related data so that it can
343     *   be reused in a new location.
344     */
345    clear: function() {
346        if(this.imgDiv) {
347            this.hide();
348            if (OpenLayers.Tile.Image.useBlankTile) { 
349                this.imgDiv.src = OpenLayers.Util.getImagesLocation() + "blank.gif";
350            }   
351        }
352    },
353
354    /**
355     * Method: initImgDiv
356     * Creates the imgDiv property on the tile.
357     */
358    initImgDiv: function() {
359       
360        var offset = this.layer.imageOffset; 
361        var size = this.layer.getImageSize(this.bounds); 
362     
363        if (this.layerAlphaHack) {
364            this.imgDiv = OpenLayers.Util.createAlphaImageDiv(null,
365                                                           offset,
366                                                           size,
367                                                           null,
368                                                           "relative",
369                                                           null,
370                                                           null,
371                                                           null,
372                                                           true);
373        } else {
374            this.imgDiv = OpenLayers.Util.createImage(null,
375                                                      offset,
376                                                      size,
377                                                      null,
378                                                      "relative",
379                                                      null,
380                                                      null,
381                                                      true);
382        }
383       
384        this.imgDiv.className = 'olTileImage';
385
386        /* checkImgURL used to be used to called as a work around, but it
387           ended up hiding problems instead of solving them and broke things
388           like relative URLs. See discussion on the dev list:
389           http://openlayers.org/pipermail/dev/2007-January/000205.html
390
391        OpenLayers.Event.observe( this.imgDiv, "load",
392            OpenLayers.Function.bind(this.checkImgURL, this) );
393        */
394        this.frame.style.zIndex = this.isBackBuffer ? 0 : 1;
395        this.frame.appendChild(this.imgDiv); 
396        this.layer.div.appendChild(this.frame); 
397
398        if(this.layer.opacity != null) {
399           
400            OpenLayers.Util.modifyDOMElement(this.imgDiv, null, null, null,
401                                             null, null, null, 
402                                             this.layer.opacity);
403        }
404
405        // we need this reference to check back the viewRequestID
406        this.imgDiv.map = this.layer.map;
407
408        //bind a listener to the onload of the image div so that we
409        // can register when a tile has finished loading.
410        var onload = function() {
411           
412            //normally isLoading should always be true here but there are some
413            // right funky conditions where loading and then reloading a tile
414            // with the same url *really*fast*. this check prevents sending
415            // a 'loadend' if the msg has already been sent
416            //
417            if (this.isLoading) { 
418                this.isLoading = false; 
419                this.events.triggerEvent("loadend"); 
420            }
421        };
422       
423        if (this.layerAlphaHack) { 
424            OpenLayers.Event.observe(this.imgDiv.childNodes[0], 'load', 
425                                     OpenLayers.Function.bind(onload, this));   
426        } else { 
427            OpenLayers.Event.observe(this.imgDiv, 'load', 
428                                 OpenLayers.Function.bind(onload, this)); 
429        } 
430       
431
432        // Bind a listener to the onerror of the image div so that we
433        // can registere when a tile has finished loading with errors.
434        var onerror = function() {
435
436            // If we have gone through all image reload attempts, it is time
437            // to realize that we are done with this image. Since
438            // OpenLayers.Util.onImageLoadError already has taken care about
439            // the error, we can continue as if the image was loaded
440            // successfully.
441            if (this.imgDiv._attempts > OpenLayers.IMAGE_RELOAD_ATTEMPTS) {
442                onload.call(this);
443            }
444        };
445        OpenLayers.Event.observe(this.imgDiv, "error",
446                                 OpenLayers.Function.bind(onerror, this));
447    },
448
449    /**
450     * Method: checkImgURL
451     * Make sure that the image that just loaded is the one this tile is meant
452     * to display, since panning/zooming might have changed the tile's URL in
453     * the meantime. If the tile URL did change before the image loaded, set
454     * the imgDiv display to 'none', as either (a) it will be reset to visible
455     * when the new URL loads in the image, or (b) we don't want to display
456     * this tile after all because its new bounds are outside our maxExtent.
457     *
458     * This function should no longer  be neccesary with the improvements to
459     * Grid.js in OpenLayers 2.3. The lack of a good isEquivilantURL function
460     * caused problems in 2.2, but it's possible that with the improved
461     * isEquivilant URL function, this might be neccesary at some point.
462     *
463     * See discussion in the thread at
464     * http://openlayers.org/pipermail/dev/2007-January/000205.html
465     */
466    checkImgURL: function () {
467        // Sometimes our image will load after it has already been removed
468        // from the map, in which case this check is not needed. 
469        if (this.layer) {
470            var loaded = this.layerAlphaHack ? this.imgDiv.firstChild.src : this.imgDiv.src;
471            if (!OpenLayers.Util.isEquivalentUrl(loaded, this.url)) {
472                this.hide();
473            }
474        }
475    },
476   
477    /**
478     * Method: startTransition
479     * This method is invoked on tiles that are backBuffers for tiles in the
480     *     grid.  The grid tile is about to be cleared and a new tile source
481     *     loaded.  This is where the transition effect needs to be started
482     *     to provide visual continuity.
483     */
484    startTransition: function() {
485        // backBufferTile has to be valid and ready to use
486        if (!this.backBufferTile || !this.backBufferTile.imgDiv) {
487            return;
488        }
489
490        // calculate the ratio of change between the current resolution of the
491        // backBufferTile and the layer.  If several animations happen in a
492        // row, then the backBufferTile will scale itself appropriately for
493        // each request.
494        var ratio = 1;
495        if (this.backBufferTile.resolution) {
496            ratio = this.backBufferTile.resolution / this.layer.getResolution();
497        }
498       
499        // if the ratio is not the same as it was last time (i.e. we are
500        // zooming), then we need to adjust the backBuffer tile
501        if (ratio != this.lastRatio) {
502            if (this.layer.transitionEffect == 'resize') {
503                // In this case, we can just immediately resize the
504                // backBufferTile.
505                var upperLeft = new OpenLayers.LonLat(
506                    this.backBufferTile.bounds.left, 
507                    this.backBufferTile.bounds.top
508                );
509                var size = new OpenLayers.Size(
510                    this.backBufferTile.size.w * ratio,
511                    this.backBufferTile.size.h * ratio
512                );
513
514                var px = this.layer.map.getLayerPxFromLonLat(upperLeft);
515                OpenLayers.Util.modifyDOMElement(this.backBufferTile.frame, 
516                                                 null, px, size);
517                var imageSize = this.backBufferTile.imageSize;
518                imageSize = new OpenLayers.Size(imageSize.w * ratio, 
519                                                imageSize.h * ratio);
520                var imageOffset = this.backBufferTile.imageOffset;
521                if(imageOffset) {
522                    imageOffset = new OpenLayers.Pixel(
523                        imageOffset.x * ratio, imageOffset.y * ratio
524                    );
525                }
526
527                OpenLayers.Util.modifyDOMElement(
528                    this.backBufferTile.imgDiv, null, imageOffset, imageSize
529                ) ;
530
531                this.backBufferTile.show();
532            }
533        } else {
534            // default effect is just to leave the existing tile
535            // until the new one loads if this is a singleTile and
536            // there was no change in resolution.  Otherwise we
537            // don't bother to show the backBufferTile at all
538            if (this.layer.singleTile) {
539                this.backBufferTile.show();
540            } else {
541                this.backBufferTile.hide();
542            }
543        }
544        this.lastRatio = ratio;
545
546    },
547   
548    /**
549     * Method: show
550     * Show the tile by showing its frame.
551     */
552    show: function() {
553        this.frame.style.display = '';
554        // Force a reflow on gecko based browsers to actually show the element
555        // before continuing execution.
556        if (OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS, 
557                this.layer.transitionEffect) != -1) {
558            if (navigator.userAgent.toLowerCase().indexOf("gecko") != -1) { 
559                this.frame.scrollLeft = this.frame.scrollLeft; 
560            } 
561        }
562    },
563   
564    /**
565     * Method: hide
566     * Hide the tile by hiding its frame.
567     */
568    hide: function() {
569        this.frame.style.display = 'none';
570    },
571   
572    CLASS_NAME: "OpenLayers.Tile.Image"
573  }
574);
575
576OpenLayers.Tile.Image.useBlankTile = ( 
577    OpenLayers.Util.getBrowserName() == "safari" || 
578    OpenLayers.Util.getBrowserName() == "opera"); 
Note: See TracBrowser for help on using the repository browser.