From 5edd3d3f84ff0a60d7eb6bc04c231dd843424311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Sat, 31 Dec 2011 00:19:19 +0100 Subject: [PATCH] make Tile.Image compatible with CSS-based tile fade animation --- lib/OpenLayers/Tile/Image.js | 49 +++++++++++++++++------ tests/Tile/Image.html | 75 +++++++++++++++++++++++++++++++++++- 2 files changed, 111 insertions(+), 13 deletions(-) diff --git a/lib/OpenLayers/Tile/Image.js b/lib/OpenLayers/Tile/Image.js index 2750e205d8..3ee6c0aa1c 100644 --- a/lib/OpenLayers/Tile/Image.js +++ b/lib/OpenLayers/Tile/Image.js @@ -80,7 +80,7 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { * transition effects are not supported if POST requests are used. */ maxGetUrlLength: null, - + /** TBD 3.0 - reorder the parameters to the init function to remove * URL. the getUrl() function on the layer gets called on * each draw(), so no need to specify it here. @@ -243,13 +243,9 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { style.width = "100%"; style.height = "100%"; } - style.display = "none"; + style.visibility = "hidden"; + style.opacity = 0; style.position = "absolute"; - if (this.layer.opacity < 1) { - OpenLayers.Util.modifyDOMElement(this.imgDiv, null, null, - null, null, null, null, - this.layer.opacity); - } if (this.layerAlphaHack) { // move the image out of sight style.paddingTop = style.height; @@ -311,7 +307,9 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { */ setImgSrc: function(url) { var img = this.imgDiv; - img.style.display = "none"; + img.style.visibility = 'hidden'; + img.style.opacity = 0; + img.style.filter = 'alpha(opacity=0)'; if (url) { img.src = url; } @@ -360,9 +358,28 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { onImageLoad: function() { var img = this.imgDiv; OpenLayers.Event.stopObservingElement(img); - img.style.display = ""; - this.isLoading = false; - this.events.triggerEvent("loadend"); + + var opacity = this.layer.opacity, + tileAnimation = this.layer.map.tileAnimation; + + if (OpenLayers.TRANSITION && tileAnimation && opacity) { + // if the displaying of the tile is animated we delay the + // loadend event until after the end of the transition, this + // to avoid flash effects because the backbuffer is removed + // before the tile is actually displayed + OpenLayers.Event.observe(img, OpenLayers.TRANSITION_END, + OpenLayers.Function.bind(this.onTransitionEnd, this) + ); + } + + img.style.visibility = 'inherit'; + img.style.opacity = opacity; + img.style.filter = 'alpha(opacity=' + (opacity * 100) + ')'; + + if (!OpenLayers.TRANSITION || !tileAnimation || !opacity) { + this.isLoading = false; + this.events.triggerEvent("loadend"); + } // IE<7 needs a reflow when the tiles are loaded because of the // percentage based positioning. Otherwise nothing is shown @@ -402,6 +419,16 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { } }, + /** + * Method: onTransitionEnd + * Handler for the transitionend event. + */ + onTransitionEnd: function() { + OpenLayers.Event.stopObservingElement(this.imgDiv); + this.isLoading = false; + this.events.triggerEvent('loadend'); + }, + CLASS_NAME: "OpenLayers.Tile.Image" }); diff --git a/tests/Tile/Image.html b/tests/Tile/Image.html index 0f71c542dd..d40849fc9a 100644 --- a/tests/Tile/Image.html +++ b/tests/Tile/Image.html @@ -262,14 +262,14 @@ tile = new OpenLayers.Tile.Image(layer, position, new OpenLayers.Bounds(-90,-85,-90,85), url, size); tile.draw(); tile.moveTo(new OpenLayers.Bounds(-185,-90,-180,-80), new OpenLayers.Pixel(-180,-85), true); - t.delay_call( 1, function() { t.eq(tile.imgDiv.style.display, "none", "Tile image is invisible.") } ); + t.delay_call( 1, function() { t.eq(tile.imgDiv.style.visibility, "hidden", "Tile image is invisible.") } ); var layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'}, {'alpha':true}); map.addLayer(layer); tile = new OpenLayers.Tile.Image(layer, position, new OpenLayers.Bounds(-90,-85,-90,85), url, size); tile.draw(); tile.moveTo(new OpenLayers.Bounds(-185,-90,-180,-80), new OpenLayers.Pixel(-180,-85), true) - t.delay_call( 1, function() { t.eq(tile.imgDiv.style.display, "none", "Alpha tile image is invisible.") } ); + t.delay_call( 1, function() { t.eq(tile.imgDiv.style.visibility, "hidden", "Alpha tile image is invisible.") } ); } @@ -342,6 +342,77 @@ t.ok(tile.imgDiv == null, "image reference removed from tile"); map.destroy(); } + + function test_onImageLoad(t) { + t.plan(12); + + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS( "OpenLayers WMS", + "http://labs.metacarta.com/wms/vmap0?", {layers: 'basic'}, {opacity: 0.5}); + map.addLayer(layer); + map.setCenter(new OpenLayers.LonLat(0,0), 5); + + var tile = layer.grid[0][0]; + + var log; + tile.events.on({loadend: function() { log++; }}); + + var T = OpenLayers.TRANSITION; + var TE = OpenLayers.TRANSITION_END; + OpenLayers.TRANSITION_END = 'transitionend'; + + function firstObserverName() { + var cacheID = tile.imgDiv._eventCacheID, + observers = OpenLayers.Event.observers[cacheID]; + return observers && observers.length > 0 ? observers[0].name : undefined; + } + + OpenLayers.TRANSITION = true; + map.tileAnimation = true; + log = 0; + tile.onImageLoad(); + t.eq(tile.imgDiv.style.visibility, 'inherit', + '[a] onImageLoad makes the image visible'); + t.eq(tile.imgDiv.style.opacity, '0.5', + '[a] onImageLoad sets the expected opacity for the image'); + t.eq(log, 0, + '[a] onImageLoad does not trigger loadend'); + t.eq(firstObserverName(), 'transitionend', + '[a] onImageLoad registers a transitionend observer'); + OpenLayers.Event.stopObservingElement(tile.imgDiv); + + OpenLayers.TRANSITION = true; + map.tileAnimation = false; + log = 0; + tile.onImageLoad(); + t.eq(tile.imgDiv.style.visibility, 'inherit', + '[b] onImageLoad makes the image visible'); + t.eq(tile.imgDiv.style.opacity, '0.5', + '[b] onImageLoad sets the expected opacity for the image'); + t.eq(log, 1, + '[b] onImageLoad does trigger loadend'); + t.eq(firstObserverName(), undefined, + '[b] onImageLoad does not register a transitionend observer'); + OpenLayers.Event.stopObservingElement(tile.imgDiv); + + OpenLayers.TRANSITION = false; + map.tileAnimation = true; + log = 0; + tile.onImageLoad(); + t.eq(tile.imgDiv.style.visibility, 'inherit', + '[c] onImageLoad makes the image visible'); + t.eq(tile.imgDiv.style.opacity, '0.5', + '[c] onImageLoad sets the expected opacity for the image'); + t.eq(log, 1, + '[c] onImageLoad does trigger loadend'); + t.eq(firstObserverName(), undefined, + '[c] onImageLoad does not register a transitionend observer'); + OpenLayers.Event.stopObservingElement(tile.imgDiv); + + map.destroy(); + OpenLayers.TRANSITION = T; + OpenLayers.TRANSITION_END = TE; + }