From afce5be5d6b256b75f5b69b975fdb51621dcf7fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Fri, 30 Dec 2011 23:23:07 +0100 Subject: [PATCH 01/25] add a tileAnimation map option --- lib/OpenLayers/Map.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/OpenLayers/Map.js b/lib/OpenLayers/Map.js index 62b5b2306d..621de8a0e4 100644 --- a/lib/OpenLayers/Map.js +++ b/lib/OpenLayers/Map.js @@ -395,6 +395,14 @@ OpenLayers.Map = OpenLayers.Class({ * the popup from getting too close to the map border. */ paddingForPopups : null, + + /** + * APIProperty: tileAnimation + * {Boolean} If set to true the olMapTileAnim class is assigned to the + * map div. This, with OpenLayers' default CSS, results in fade-in + * effects when image tiles are displayed. + */ + tileAnimation: true, /** * Property: minPx @@ -500,6 +508,9 @@ OpenLayers.Map = OpenLayers.Class({ } OpenLayers.Element.addClass(this.div, 'olMap'); + if (this.tileAnimation) { + OpenLayers.Element.addClass(this.div, 'olMapTileAnim'); + } // the viewPortDiv is the outermost div we modify var id = this.id + "_OpenLayers_ViewPort"; From 04f72a0e07b15eadfd31e81ee9de096b4dd48bf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Fri, 30 Dec 2011 23:28:21 +0100 Subject: [PATCH 02/25] tests for the tileAnimation map option --- tests/Map.html | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/Map.html b/tests/Map.html index faad0b30c7..4f2c37b656 100644 --- a/tests/Map.html +++ b/tests/Map.html @@ -115,6 +115,24 @@ map.destroy(); } + function test_Map_constructor_tileanim(t) { + t.plan(4); + + map = new OpenLayers.Map("map"); + t.eq(map.tileAnimation, true, + 'tileAnimation is true by default'); + t.ok(OpenLayers.Element.hasClass(map.div, 'olMapTileAnim'), + 'map div is assigned the olMapTileAnim class by default'); + map.destroy(); + + map = new OpenLayers.Map("map", {tileAnimation: false}); + t.eq(map.tileAnimation, false, + 'tileAnimation is false if option is false'); + t.ok(OpenLayers.Element.hasClass(map.div, 'olMapTileAnim'), + 'map div not assigned the olMapTileAnim class if tileAnimation is false'); + map.destroy(); + } + function test_Map_setOptions(t) { t.plan(2); map = new OpenLayers.Map('map', {maxExtent: new OpenLayers.Bounds(100, 200, 300, 400)}); From d417231bb835fefc385a5c7284accc2f0c28dd8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Sat, 31 Dec 2011 00:17:36 +0100 Subject: [PATCH 03/25] add OpenLayers.TRANSITION and OpenLayers.TRANSITION_END private constants --- lib/OpenLayers/Util.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/lib/OpenLayers/Util.js b/lib/OpenLayers/Util.js index a907e03023..a5a2a96246 100644 --- a/lib/OpenLayers/Util.js +++ b/lib/OpenLayers/Util.js @@ -1435,6 +1435,34 @@ OpenLayers.BROWSER_NAME = (function() { return name; })(); +(function() { + function testProp(props) { + var style = document.documentElement.style; + for (var i=0; i Date: Sat, 31 Dec 2011 00:19:19 +0100 Subject: [PATCH 04/25] 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; + } From 6b918bc9ab3674d09e3a83aaa69dbe56b08950d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Sat, 31 Dec 2011 00:19:44 +0100 Subject: [PATCH 05/25] make the Layer/Image.html tests pass again --- tests/Layer/Image.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Layer/Image.html b/tests/Layer/Image.html index a11caa5260..4d4219284f 100644 --- a/tests/Layer/Image.html +++ b/tests/Layer/Image.html @@ -128,7 +128,7 @@ function test_loadEvents(t) { t.plan(3); - var map = new OpenLayers.Map('map'); + var map = new OpenLayers.Map('map', {tileAnimation: false}); var layer = new OpenLayers.Layer.Image( 'Test', '../../img/blank.gif', new OpenLayers.Bounds(-180, -88.759, 180, 88.759), From df7ab415d0a4c213a4b3a9b5e9cd81438d491676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Sat, 31 Dec 2011 00:20:06 +0100 Subject: [PATCH 06/25] add css rule for tile animation --- theme/default/style.css | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/theme/default/style.css b/theme/default/style.css index ea8e520890..64bec7d29c 100644 --- a/theme/default/style.css +++ b/theme/default/style.css @@ -428,3 +428,14 @@ span.olGoogleAttribution.hybrid a, span.olGoogleAttribution.satellite a { .olControlEditingToolbar .olControlDrawFeaturePolygonItemActive { background-position: -26px -24px; } + +/** + * Animations + */ + +.olMapTileAnim .olTileImage { + -webkit-transition: opacity 0.2s linear; + -moz-transition: opacity 0.2s linear; + -o-transition: opacity 0.2s linear; + transition: opacity 0.2s linear; +} From afc0283c06c13ae45fadab5d225bcc25d8513f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Sat, 31 Dec 2011 00:45:15 +0100 Subject: [PATCH 07/25] fix the Layer.WMS setOpacity tests --- tests/Layer/WMS.html | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/Layer/WMS.html b/tests/Layer/WMS.html index a07b36c1d9..f18a0d7598 100644 --- a/tests/Layer/WMS.html +++ b/tests/Layer/WMS.html @@ -275,22 +275,29 @@ t.plan( 5 ); var map = new OpenLayers.Map('map'); - map.projection = "xx"; tUrl = "http://octo.metacarta.com/cgi-bin/mapserv"; tParams = { layers: 'basic', format: 'image/png'}; tOptions = { 'opacity': '0.5' }; var tLayer = new OpenLayers.Layer.WMS(name, tUrl, tParams, tOptions); map.addLayer(tLayer); - map.zoomToMaxExtent(); + map.setCenter(new OpenLayers.LonLat(0,0), 5); + + var tile = tLayer.grid[0][0], + tileImg = tile.imgDiv; + t.eq(tLayer.opacity, "0.5", "Opacity is set correctly"); - t.eq(parseFloat(tLayer.div.firstChild.style.opacity), 0.5, "Opacity on tile is correct"); + tile.onImageLoad(); // simulate a 'load' image event + t.eq(parseFloat(tileImg.style.opacity), 0.5, "Opacity on tile is correct"); + tLayer.setOpacity("0.6"); t.eq(tLayer.opacity, "0.6", "setOpacity works properly"); - t.eq(parseFloat(tLayer.div.firstChild.style.opacity), 0.6, "Opacity on tile is changed correctly"); + t.eq(parseFloat(tileImg.style.opacity), 0.6, "Opacity on tile is changed correctly"); + var pixel = new OpenLayers.Pixel(5,6); var tile = tLayer.addTile(new OpenLayers.Bounds(1,2,3,4), pixel); tile.draw(); + tile.onImageLoad(); // simulate a 'load' image event t.eq(parseFloat(tile.imgDiv.style.opacity), 0.6, "Tile opacity is set correctly"); map.destroy(); From e7ef3d6c21ebd3ad4d81e850cf73f5c0b49e1739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Sat, 31 Dec 2011 12:23:32 +0100 Subject: [PATCH 08/25] remove duplicated setOpacity tests --- tests/Layer/ArcGIS93Rest.html | 25 ------------------------- tests/Layer/Grid.html | 32 ++++++++++++++++++++++++++++++++ tests/Layer/MapServer.html | 25 ------------------------- tests/Layer/WMS.html | 32 -------------------------------- 4 files changed, 32 insertions(+), 82 deletions(-) diff --git a/tests/Layer/ArcGIS93Rest.html b/tests/Layer/ArcGIS93Rest.html index 4f1a4c618d..4a57b70c12 100644 --- a/tests/Layer/ArcGIS93Rest.html +++ b/tests/Layer/ArcGIS93Rest.html @@ -190,31 +190,6 @@ } - function test_Layer_AGS93_setOpacity (t) { - var params = {layers: "show:0,2"}; - t.plan( 5 ); - - var map = new OpenLayers.Map('map'); - map.projection = "xx"; - tParams = { layers: 'show:0,2', - format: 'png'}; - tOptions = { 'opacity': '0.5' }; - var tLayer = new OpenLayers.Layer.ArcGIS93Rest(name, url, tParams, tOptions); - map.addLayer(tLayer); - map.zoomToMaxExtent(); - t.eq(tLayer.opacity, "0.5", "Opacity is set correctly"); - t.eq(parseFloat(tLayer.div.firstChild.style.opacity), 0.5, "Opacity on tile is correct"); - tLayer.setOpacity("0.6"); - t.eq(tLayer.opacity, "0.6", "setOpacity works properly"); - t.eq(parseFloat(tLayer.div.firstChild.style.opacity), 0.6, "Opacity on tile is changed correctly"); - var pixel = new OpenLayers.Pixel(5,6); - var tile = tLayer.addTile(new OpenLayers.Bounds(1,2,3,4), pixel); - tile.draw(); - t.eq(parseFloat(tile.imgDiv.style.opacity), 0.6, "Tile opacity is set correctly"); - - map.destroy(); - } - function test_Layer_AGS93_noGutters (t) { t.plan(2); var map = new OpenLayers.Map('map'); diff --git a/tests/Layer/Grid.html b/tests/Layer/Grid.html index 0c5c747559..eae762735c 100644 --- a/tests/Layer/Grid.html +++ b/tests/Layer/Grid.html @@ -639,6 +639,38 @@ t.eq( layer.grid, null, "layer.grid is null after destroy" ); t.eq( layer.tileSize, null, "layer.tileSize is null after destroy" ); } + + function test_setOpacity(t) { + + t.plan(5); + + var map = new OpenLayers.Map('map'); + var layer = new OpenLayers.Layer.WMS('', '', {}, { + isBaseLayer: true, + opacity: '0.6' + }); + map.addLayer(layer); + // setCenter adds tiles to the layer's grid + map.setCenter(new OpenLayers.LonLat(0, 0), 5); + + var tile = layer.grid[0][0], tileImg = tile.imgDiv; + + tile.onImageLoad(); // simulate an image load event + t.eq(layer.opacity, '0.6', 'layer opacity value is correct'); + t.eq(parseFloat(tileImg.style.opacity), 0.6, 'tile opacity is correct'); + + layer.setOpacity('0.2'); + t.eq(layer.opacity, '0.2', 'layer opacity value is correct'); + t.eq(parseFloat(tileImg.style.opacity), 0.2, 'tile opacity is correct'); + + tile = layer.addTile(new OpenLayers.Bounds(1, 2, 3, 4), + new OpenLayers.Pixel(5, 6)); + tile.draw(); // add tile to the grid + tile.onImageLoad(); // simulate an image load event + t.eq(parseFloat(tile.imgDiv.style.opacity), 0.2, "tile opacity is correc"); + + map.destroy(); + } function test_getServerResolution(t) { diff --git a/tests/Layer/MapServer.html b/tests/Layer/MapServer.html index 11173cb14b..004731db49 100644 --- a/tests/Layer/MapServer.html +++ b/tests/Layer/MapServer.html @@ -190,31 +190,6 @@ } - function test_Layer_MapServer_setOpacity (t) { - t.plan( 5 ); - - var map = new OpenLayers.Map('map'); - map.projection = "xx"; - tUrl = "http://labs.metacarta.com/cgi-bin/mapserv"; - tParams = { layers: 'basic', - format: 'image/png'}; - tOptions = { 'opacity': '0.5' }; - var tLayer = new OpenLayers.Layer.MapServer(name, tUrl, tParams, tOptions); - map.addLayer(tLayer); - map.zoomToMaxExtent(); - t.eq(tLayer.opacity, "0.5", "Opacity is set correctly"); - t.eq(parseFloat(tLayer.div.firstChild.style.opacity), 0.5, "Opacity on tile is correct"); - tLayer.setOpacity("0.6"); - t.eq(tLayer.opacity, "0.6", "setOpacity works properly"); - t.eq(parseFloat(tLayer.div.firstChild.style.opacity), 0.6, "Opacity on tile is changed correctly"); - var pixel = new OpenLayers.Pixel(5,6); - var tile = tLayer.addTile(new OpenLayers.Bounds(1,2,3,4), pixel); - tile.draw(); - t.eq(parseFloat(tile.imgDiv.style.opacity), 0.6, "Tile opacity is set correctly"); - map.destroy(); - - } - function test_Layer_MapServer_singleTile (t) { t.plan( 5 ); var map = new OpenLayers.Map('map'); diff --git a/tests/Layer/WMS.html b/tests/Layer/WMS.html index f18a0d7598..757c6b92b2 100644 --- a/tests/Layer/WMS.html +++ b/tests/Layer/WMS.html @@ -271,38 +271,6 @@ } - function test_Layer_WMS_setOpacity (t) { - t.plan( 5 ); - - var map = new OpenLayers.Map('map'); - tUrl = "http://octo.metacarta.com/cgi-bin/mapserv"; - tParams = { layers: 'basic', - format: 'image/png'}; - tOptions = { 'opacity': '0.5' }; - var tLayer = new OpenLayers.Layer.WMS(name, tUrl, tParams, tOptions); - map.addLayer(tLayer); - map.setCenter(new OpenLayers.LonLat(0,0), 5); - - var tile = tLayer.grid[0][0], - tileImg = tile.imgDiv; - - t.eq(tLayer.opacity, "0.5", "Opacity is set correctly"); - tile.onImageLoad(); // simulate a 'load' image event - t.eq(parseFloat(tileImg.style.opacity), 0.5, "Opacity on tile is correct"); - - tLayer.setOpacity("0.6"); - t.eq(tLayer.opacity, "0.6", "setOpacity works properly"); - t.eq(parseFloat(tileImg.style.opacity), 0.6, "Opacity on tile is changed correctly"); - - var pixel = new OpenLayers.Pixel(5,6); - var tile = tLayer.addTile(new OpenLayers.Bounds(1,2,3,4), pixel); - tile.draw(); - tile.onImageLoad(); // simulate a 'load' image event - t.eq(parseFloat(tile.imgDiv.style.opacity), 0.6, "Tile opacity is set correctly"); - - map.destroy(); - } - function test_Layer_WMS_noGutters (t) { t.plan(2); var map = new OpenLayers.Map('map'); From d2856cd721203bbe04a6079294f154eb5319da0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Sat, 31 Dec 2011 12:25:37 +0100 Subject: [PATCH 09/25] remove duplicated setOpacity tests (MapServer/Untiled.html) --- tests/deprecated/Layer/MapServer/Untiled.html | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/tests/deprecated/Layer/MapServer/Untiled.html b/tests/deprecated/Layer/MapServer/Untiled.html index fd9e5adfdd..1b1dc94f36 100644 --- a/tests/deprecated/Layer/MapServer/Untiled.html +++ b/tests/deprecated/Layer/MapServer/Untiled.html @@ -118,27 +118,6 @@ } - function test_Layer_MapServer_Untiled_setOpacity (t) { - t.plan( 4 ); - - var map = new OpenLayers.Map('map'); - map.projection = "xx"; - tUrl = "http://labs.metacarta.com/cgi-bin/mapserv"; - tParams = { layers: 'basic', - format: 'image/png'}; - tOptions = { 'opacity': '0.5' }; - var tLayer = new OpenLayers.Layer.MapServer.Untiled(name, tUrl, tParams, tOptions); - map.addLayer(tLayer); - map.zoomToMaxExtent(); - t.eq(tLayer.opacity, "0.5", "Opacity is set correctly"); - t.eq(parseFloat(tLayer.div.firstChild.style.opacity), 0.5, "Opacity on tile is correct"); - tLayer.setOpacity("0.6"); - t.eq(tLayer.opacity, "0.6", "setOpacity works properly"); - t.eq(parseFloat(tLayer.div.firstChild.style.opacity), 0.6, "Opacity on tile is changed correctly"); - map.destroy(); - - } - // DEPRECATED -- REMOVE IN 3.0 function test_Layer_Untiled_MapServer(t) { t.plan(1); From 587650e01b7b8f72a22c585cc2f654de7a726ee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Sat, 31 Dec 2011 14:09:24 +0100 Subject: [PATCH 10/25] use parseFloat to read opacity style values in tests --- tests/Tile/Image.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Tile/Image.html b/tests/Tile/Image.html index d40849fc9a..18e0be38dc 100644 --- a/tests/Tile/Image.html +++ b/tests/Tile/Image.html @@ -373,7 +373,7 @@ tile.onImageLoad(); t.eq(tile.imgDiv.style.visibility, 'inherit', '[a] onImageLoad makes the image visible'); - t.eq(tile.imgDiv.style.opacity, '0.5', + t.eq(parseFloat(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'); @@ -387,7 +387,7 @@ tile.onImageLoad(); t.eq(tile.imgDiv.style.visibility, 'inherit', '[b] onImageLoad makes the image visible'); - t.eq(tile.imgDiv.style.opacity, '0.5', + t.eq(parseFloat(tile.imgDiv.style.opacity), 0.5, '[b] onImageLoad sets the expected opacity for the image'); t.eq(log, 1, '[b] onImageLoad does trigger loadend'); @@ -401,7 +401,7 @@ tile.onImageLoad(); t.eq(tile.imgDiv.style.visibility, 'inherit', '[c] onImageLoad makes the image visible'); - t.eq(tile.imgDiv.style.opacity, '0.5', + t.eq(parseFloat(tile.imgDiv.style.opacity), 0.5, '[c] onImageLoad sets the expected opacity for the image'); t.eq(log, 1, '[c] onImageLoad does trigger loadend'); From e11e4358fa1417d11f19e719db5e8da02cbf80d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Sat, 31 Dec 2011 14:13:42 +0100 Subject: [PATCH 11/25] add olMapTileAnim rule in style.mobile.css --- examples/style.mobile.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/style.mobile.css b/examples/style.mobile.css index 31c27ffd92..f5c61ab0ac 100644 --- a/examples/style.mobile.css +++ b/examples/style.mobile.css @@ -23,3 +23,9 @@ div.olControlZoomPanel .olControlZoomOutItemInactive { top: 72px; background-position: 0 -72px; } +.olMapTileAnim .olTileImage { + -webkit-transition: opacity 0.2s linear; + -moz-transition: opacity 0.2s linear; + -o-transition: opacity 0.2s linear; + transition: opacity 0.2s linear; +} From b7b0d6b7121fca91f012fa7700918381ef7168b3 Mon Sep 17 00:00:00 2001 From: tschaub Date: Mon, 2 Jan 2012 11:40:50 -0700 Subject: [PATCH 12/25] Collecting image tile changes in the Image.js. --- lib/OpenLayers/Tile/Image.js | 37 +++++++++++++++++++++++++++++++++--- lib/OpenLayers/Util.js | 28 --------------------------- tests/Tile/Image.html | 16 ++++++++-------- 3 files changed, 42 insertions(+), 39 deletions(-) diff --git a/lib/OpenLayers/Tile/Image.js b/lib/OpenLayers/Tile/Image.js index 3ee6c0aa1c..1a4ce1ffa0 100644 --- a/lib/OpenLayers/Tile/Image.js +++ b/lib/OpenLayers/Tile/Image.js @@ -362,12 +362,12 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { var opacity = this.layer.opacity, tileAnimation = this.layer.map.tileAnimation; - if (OpenLayers.TRANSITION && tileAnimation && opacity) { + if (OpenLayers.Tile.Image.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.Event.observe(img, OpenLayers.Tile.Image.TRANSITION_END, OpenLayers.Function.bind(this.onTransitionEnd, this) ); } @@ -376,7 +376,7 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { img.style.opacity = opacity; img.style.filter = 'alpha(opacity=' + (opacity * 100) + ')'; - if (!OpenLayers.TRANSITION || !tileAnimation || !opacity) { + if (!OpenLayers.Tile.Image.TRANSITION || !tileAnimation || !opacity) { this.isLoading = false; this.events.triggerEvent("loadend"); } @@ -432,3 +432,34 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { CLASS_NAME: "OpenLayers.Tile.Image" }); + +// Test for support of CSS transitions and store appropriate property names +(function() { + function testProp(props) { + var style = document.documentElement.style; + for (var i=0; i 0 ? observers[0].name : undefined; } - OpenLayers.TRANSITION = true; + OpenLayers.Tile.Image.TRANSITION = true; map.tileAnimation = true; log = 0; tile.onImageLoad(); @@ -381,7 +381,7 @@ '[a] onImageLoad registers a transitionend observer'); OpenLayers.Event.stopObservingElement(tile.imgDiv); - OpenLayers.TRANSITION = true; + OpenLayers.Tile.Image.TRANSITION = true; map.tileAnimation = false; log = 0; tile.onImageLoad(); @@ -395,7 +395,7 @@ '[b] onImageLoad does not register a transitionend observer'); OpenLayers.Event.stopObservingElement(tile.imgDiv); - OpenLayers.TRANSITION = false; + OpenLayers.Tile.Image.TRANSITION = false; map.tileAnimation = true; log = 0; tile.onImageLoad(); @@ -410,8 +410,8 @@ OpenLayers.Event.stopObservingElement(tile.imgDiv); map.destroy(); - OpenLayers.TRANSITION = T; - OpenLayers.TRANSITION_END = TE; + OpenLayers.Tile.Image.TRANSITION = T; + OpenLayers.Tile.Image.TRANSITION_END = TE; } From 3eb34f587ec758a6aff28d63d0567cfe460f4100 Mon Sep 17 00:00:00 2001 From: tschaub Date: Mon, 2 Jan 2012 11:52:54 -0700 Subject: [PATCH 13/25] Add test for setOpacity. --- tests/Layer/WMS.html | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/Layer/WMS.html b/tests/Layer/WMS.html index 757c6b92b2..61c7f126e1 100644 --- a/tests/Layer/WMS.html +++ b/tests/Layer/WMS.html @@ -271,6 +271,25 @@ } + function test_setOpacity(t) { + t.plan(1); + + var layer = new OpenLayers.Layer.WMS( + null, "/bogus/wms", {layers: "mylayer"} + ); + var map = new OpenLayers.Map("map"); + map.addLayer(layer); + + map.zoomToMaxExtent(); + + layer.setOpacity(0.5); + t.delay_call(1, function() { + t.eq(parseFloat(layer.div.firstChild.style.opacity), 0.5, "opacity set"); + map.destroy(); + }); + } + + function test_Layer_WMS_noGutters (t) { t.plan(2); var map = new OpenLayers.Map('map'); From eb924c8f776e822a8000df778f8bc96b22855d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Mon, 2 Jan 2012 22:53:53 +0100 Subject: [PATCH 14/25] no longer rely on the transitionend event, unwanted flashes are avoid using a timer --- lib/OpenLayers/Layer/Grid.js | 34 ++++++++++++++++++++--- lib/OpenLayers/Tile/Image.js | 54 +++--------------------------------- tests/Tile/Image.html | 53 +++-------------------------------- 3 files changed, 38 insertions(+), 103 deletions(-) diff --git a/lib/OpenLayers/Layer/Grid.js b/lib/OpenLayers/Layer/Grid.js index a7c10f8ff6..b75edc91f7 100644 --- a/lib/OpenLayers/Layer/Grid.js +++ b/lib/OpenLayers/Layer/Grid.js @@ -138,6 +138,14 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { */ backBufferLonLat: null, + /** + * Property; backBufferTimerId + * {Number} The id of the back buffer timer. This timer is used to + * delay the removal of the back buffer, thereby preventing + * flash effects caused by tile animation. + */ + backBufferTimerId: null, + /** * Register a listener for a particular event with the following syntax: * (code) @@ -190,6 +198,10 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { window.clearTimeout(this.timerId); this.timerId = null; } + if(this.backBufferTimerId !== null) { + window.clearTimeout(this.backBufferTimerId); + this.backBufferTimerId = null; + } }, /** @@ -197,9 +209,8 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { * Deconstruct the layer and clear the grid. */ destroy: function() { + this.removeBackBuffer(); this.clearGrid(); - // clearGrid should remove any back buffer from the layer, - // so no need to call removeBackBuffer here this.grid = null; this.tileSize = null; @@ -530,6 +541,17 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { } }, + /** + * Method: scheduleBackBufferRemoval + */ + scheduleBackBufferRemoval: function() { + if(this.backBufferTimerId !== null) { + window.clearTimeout(this.backBufferTimerId); + } + this.backBufferTimerId = window.setTimeout( + OpenLayers.Function.bind(this.removeBackBuffer, this), 800); + }, + /** * Method: moveByPx * Move the layer based on pixel vector. @@ -930,8 +952,12 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { //if that was the last tile, then trigger a 'loadend' on the layer if (this.numLoadingTiles == 0) { this.events.triggerEvent("loadend"); - this.removeBackBuffer(); - } + if(this.backBuffer) { + // the removal of the back buffer is delayed to prevent flash + // effects due to the animation of tile displaying + this.scheduleBackBufferRemoval(); + } + } }; tile.events.register("loadend", this, tile.onLoadEnd); tile.events.register("unload", this, tile.onLoadEnd); diff --git a/lib/OpenLayers/Tile/Image.js b/lib/OpenLayers/Tile/Image.js index 1a4ce1ffa0..a8340e1132 100644 --- a/lib/OpenLayers/Tile/Image.js +++ b/lib/OpenLayers/Tile/Image.js @@ -359,27 +359,12 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { var img = this.imgDiv; OpenLayers.Event.stopObservingElement(img); - var opacity = this.layer.opacity, - tileAnimation = this.layer.map.tileAnimation; - - if (OpenLayers.Tile.Image.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.Tile.Image.TRANSITION_END, - OpenLayers.Function.bind(this.onTransitionEnd, this) - ); - } - img.style.visibility = 'inherit'; - img.style.opacity = opacity; - img.style.filter = 'alpha(opacity=' + (opacity * 100) + ')'; + img.style.opacity = this.layer.opacity; + img.style.filter = 'alpha(opacity=' + (this.layer.opacity * 100) + ')'; - if (!OpenLayers.Tile.Image.TRANSITION || !tileAnimation || !opacity) { - this.isLoading = false; - this.events.triggerEvent("loadend"); - } + 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 @@ -432,34 +417,3 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { CLASS_NAME: "OpenLayers.Tile.Image" }); - -// Test for support of CSS transitions and store appropriate property names -(function() { - function testProp(props) { - var style = document.documentElement.style; - for (var i=0; i 0 ? observers[0].name : undefined; - } - - OpenLayers.Tile.Image.TRANSITION = true; - map.tileAnimation = true; log = 0; tile.onImageLoad(); t.eq(tile.imgDiv.style.visibility, 'inherit', - '[a] onImageLoad makes the image visible'); + 'onImageLoad makes the image visible'); t.eq(parseFloat(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.Tile.Image.TRANSITION = true; - map.tileAnimation = false; - log = 0; - tile.onImageLoad(); - t.eq(tile.imgDiv.style.visibility, 'inherit', - '[b] onImageLoad makes the image visible'); - t.eq(parseFloat(tile.imgDiv.style.opacity), 0.5, - '[b] onImageLoad sets the expected opacity for the image'); + '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.Tile.Image.TRANSITION = false; - map.tileAnimation = true; - log = 0; - tile.onImageLoad(); - t.eq(tile.imgDiv.style.visibility, 'inherit', - '[c] onImageLoad makes the image visible'); - t.eq(parseFloat(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); + 'onImageLoad does not trigger loadend'); map.destroy(); - OpenLayers.Tile.Image.TRANSITION = T; - OpenLayers.Tile.Image.TRANSITION_END = TE; } From fcb9a6cd2c3b8d50339a6436b6c3d99cf8970eda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Mon, 2 Jan 2012 23:20:15 +0100 Subject: [PATCH 15/25] remove Tile.Image.onTransitionEnd - it is no longer used --- lib/OpenLayers/Tile/Image.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/OpenLayers/Tile/Image.js b/lib/OpenLayers/Tile/Image.js index a8340e1132..5fee2fd559 100644 --- a/lib/OpenLayers/Tile/Image.js +++ b/lib/OpenLayers/Tile/Image.js @@ -404,16 +404,6 @@ 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" }); From 78963a5fa84a07bba5fbe29e77e1c06c5bfe2e15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Mon, 2 Jan 2012 23:34:02 +0100 Subject: [PATCH 16/25] correct typo in tests/Tile/Image.html, @tschaub has sharp eyes --- tests/Tile/Image.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Tile/Image.html b/tests/Tile/Image.html index 1bccb72ecd..51f28b0510 100644 --- a/tests/Tile/Image.html +++ b/tests/Tile/Image.html @@ -364,7 +364,7 @@ t.eq(parseFloat(tile.imgDiv.style.opacity), 0.5, 'onImageLoad sets the expected opacity for the image'); t.eq(log, 1, - 'onImageLoad does not trigger loadend'); + 'onImageLoad does trigger loadend'); map.destroy(); } From 3c910c88018e92ea2e8f44f8279f6d46055064c3 Mon Sep 17 00:00:00 2001 From: tschaub Date: Mon, 2 Jan 2012 15:49:55 -0700 Subject: [PATCH 17/25] Removing the tileAnimation map property. Edit CSS to change the style. --- lib/OpenLayers/Map.js | 11 ----------- tests/Layer/Image.html | 2 +- tests/Map.html | 18 ------------------ theme/default/style.css | 2 +- 4 files changed, 2 insertions(+), 31 deletions(-) diff --git a/lib/OpenLayers/Map.js b/lib/OpenLayers/Map.js index 621de8a0e4..62b5b2306d 100644 --- a/lib/OpenLayers/Map.js +++ b/lib/OpenLayers/Map.js @@ -395,14 +395,6 @@ OpenLayers.Map = OpenLayers.Class({ * the popup from getting too close to the map border. */ paddingForPopups : null, - - /** - * APIProperty: tileAnimation - * {Boolean} If set to true the olMapTileAnim class is assigned to the - * map div. This, with OpenLayers' default CSS, results in fade-in - * effects when image tiles are displayed. - */ - tileAnimation: true, /** * Property: minPx @@ -508,9 +500,6 @@ OpenLayers.Map = OpenLayers.Class({ } OpenLayers.Element.addClass(this.div, 'olMap'); - if (this.tileAnimation) { - OpenLayers.Element.addClass(this.div, 'olMapTileAnim'); - } // the viewPortDiv is the outermost div we modify var id = this.id + "_OpenLayers_ViewPort"; diff --git a/tests/Layer/Image.html b/tests/Layer/Image.html index 4d4219284f..05ab5c378f 100644 --- a/tests/Layer/Image.html +++ b/tests/Layer/Image.html @@ -128,7 +128,7 @@ function test_loadEvents(t) { t.plan(3); - var map = new OpenLayers.Map('map', {tileAnimation: false}); + var map = new OpenLayers.Map('map'); var layer = new OpenLayers.Layer.Image( 'Test', '../../img/blank.gif', new OpenLayers.Bounds(-180, -88.759, 180, 88.759), diff --git a/tests/Map.html b/tests/Map.html index 4f2c37b656..faad0b30c7 100644 --- a/tests/Map.html +++ b/tests/Map.html @@ -115,24 +115,6 @@ map.destroy(); } - function test_Map_constructor_tileanim(t) { - t.plan(4); - - map = new OpenLayers.Map("map"); - t.eq(map.tileAnimation, true, - 'tileAnimation is true by default'); - t.ok(OpenLayers.Element.hasClass(map.div, 'olMapTileAnim'), - 'map div is assigned the olMapTileAnim class by default'); - map.destroy(); - - map = new OpenLayers.Map("map", {tileAnimation: false}); - t.eq(map.tileAnimation, false, - 'tileAnimation is false if option is false'); - t.ok(OpenLayers.Element.hasClass(map.div, 'olMapTileAnim'), - 'map div not assigned the olMapTileAnim class if tileAnimation is false'); - map.destroy(); - } - function test_Map_setOptions(t) { t.plan(2); map = new OpenLayers.Map('map', {maxExtent: new OpenLayers.Bounds(100, 200, 300, 400)}); diff --git a/theme/default/style.css b/theme/default/style.css index 64bec7d29c..c695689ff7 100644 --- a/theme/default/style.css +++ b/theme/default/style.css @@ -433,7 +433,7 @@ span.olGoogleAttribution.hybrid a, span.olGoogleAttribution.satellite a { * Animations */ -.olMapTileAnim .olTileImage { +.olTileImage { -webkit-transition: opacity 0.2s linear; -moz-transition: opacity 0.2s linear; -o-transition: opacity 0.2s linear; From f2168d13b7559d487afe5de8e9ea08eb581420da Mon Sep 17 00:00:00 2001 From: tschaub Date: Mon, 2 Jan 2012 16:07:40 -0700 Subject: [PATCH 18/25] Increase timeout to avoid flashes. Without this change, flashes are fairly frequent while zooming around a full screen map. --- examples/fullScreen.html | 6 +++--- examples/fullScreen.js | 32 +++++++++++++++++++------------- lib/OpenLayers/Layer/Grid.js | 2 +- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/examples/fullScreen.html b/examples/fullScreen.html index 7a92debd56..f5df04a21f 100644 --- a/examples/fullScreen.html +++ b/examples/fullScreen.html @@ -25,9 +25,8 @@ } - - +
@@ -38,7 +37,7 @@

- Demonstrate a map that fill the entire browser window. + Demonstrate a map that fills the entire browser window.

@@ -48,6 +47,7 @@ fullScreen.js source to see how this is done.

+ diff --git a/examples/fullScreen.js b/examples/fullScreen.js index 93ed57a027..e2ad311d19 100644 --- a/examples/fullScreen.js +++ b/examples/fullScreen.js @@ -1,15 +1,21 @@ -var map; -function init(){ - map = new OpenLayers.Map('map'); +var urls = [ + "http://a.tile.openstreetmap.org/${z}/${x}/${y}.png", + "http://b.tile.openstreetmap.org/${z}/${x}/${y}.png", + "http://c.tile.openstreetmap.org/${z}/${x}/${y}.png" +]; - var ol_wms = new OpenLayers.Layer.WMS( "OpenLayers WMS", - "http://vmap0.tiles.osgeo.org/wms/vmap0", - {layers: 'basic'} ); - var ol_wms_nobuffer = new OpenLayers.Layer.WMS( "OpenLayers WMS (no tile buffer)", - "http://vmap0.tiles.osgeo.org/wms/vmap0", - {layers: 'basic'}, {buffer: 0}); +var map = new OpenLayers.Map({ + div: "map", + layers: [ + new OpenLayers.Layer.XYZ("OSM (with buffer)", urls, { + transitionEffect: "resize", buffer: 2, sphericalMercator: true + }), + new OpenLayers.Layer.XYZ("OSM (without buffer)", urls, { + transitionEffect: "resize", buffer: 0, sphericalMercator: true + }) + ], + center: [0, 0], + zoom: 3 +}); - map.addLayers([ol_wms, ol_wms_nobuffer]); - map.addControl(new OpenLayers.Control.LayerSwitcher()); - map.setCenter(new OpenLayers.LonLat(0, 0), 6); -} +map.addControl(new OpenLayers.Control.LayerSwitcher()); \ No newline at end of file diff --git a/lib/OpenLayers/Layer/Grid.js b/lib/OpenLayers/Layer/Grid.js index b75edc91f7..976eb674ef 100644 --- a/lib/OpenLayers/Layer/Grid.js +++ b/lib/OpenLayers/Layer/Grid.js @@ -549,7 +549,7 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { window.clearTimeout(this.backBufferTimerId); } this.backBufferTimerId = window.setTimeout( - OpenLayers.Function.bind(this.removeBackBuffer, this), 800); + OpenLayers.Function.bind(this.removeBackBuffer, this), 2500); }, /** From 5914cb3566c5f14009f01f9498720f9db48db9da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 3 Jan 2012 08:24:41 +0100 Subject: [PATCH 19/25] enable kinetic dragging in the full-screen example --- examples/fullScreen.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/examples/fullScreen.js b/examples/fullScreen.js index e2ad311d19..dc8ed19d1a 100644 --- a/examples/fullScreen.js +++ b/examples/fullScreen.js @@ -14,8 +14,17 @@ var map = new OpenLayers.Map({ transitionEffect: "resize", buffer: 0, sphericalMercator: true }) ], + controls: [ + new OpenLayers.Control.Navigation({ + dragPanOptions: { + enableKinetic: true + } + }), + new OpenLayers.Control.PanZoom(), + new OpenLayers.Control.Attribution() + ], center: [0, 0], zoom: 3 }); -map.addControl(new OpenLayers.Control.LayerSwitcher()); \ No newline at end of file +map.addControl(new OpenLayers.Control.LayerSwitcher()); From 9064ba8c6aa46ae3fb384680f4c88b80c2f72854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 3 Jan 2012 08:24:58 +0100 Subject: [PATCH 20/25] add release notes for tile animation --- notes/2.12.md | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/notes/2.12.md b/notes/2.12.md index 97111ed53e..eaad3e9753 100644 --- a/notes/2.12.md +++ b/notes/2.12.md @@ -1,3 +1,60 @@ +# Major enhancements + +## Tile animation + +The displaying of tiles can now be animated, using CSS3 transitions. Transitions operate on the `opacity` property. Here's the CSS rule defined in OpenLayers' default theme: + + .olTileImage { + -webkit-transition: opacity 0.2s linear; + -moz-transition: opacity 0.2s linear; + -o-transition: opacity 0.2s linear; + transition: opacity 0.2s linear; + } + +People can override this rule to use other transition settings. To remove tile animation entirely use: + + .olTileImage { + -webkit-transition: none; + -moz-transition: none; + -o-transition: all 0 none; + transition: none; + } + +# Behavior Changes from Past Releases + +## Function return values + +[Previously][prev] a few functions in the library displayed error messages and returned `undefined`, `null` or `false` if the parameters passed in were bad. In 2.12 these functions now just throw an error/exception. People relying on return values to know if a function call is successful may need to change their code. Here are the modified functions: + + * `OpenLayers.Bounds.add` throws a `TypeError` exception if `x` or `y` is null + * `OpenLayers.LonLat.add` throws a `TypeError` exception if `lon` or `lat` is null + * `OpenLayers.Pixel.add` throws a `TypeError` exception if `x` or `y` is null + * `OpenLayers.Filter.Comparison.value2regex` throws an `Error` exception if `wildcard` equals to `"."` + * `OpenLayers.Layer.PointTrack.addNodes` throws a `TypeError` exception if `endPoint` isn't actually a point + * `OpenLayers.Layer.Vector.getFeatureFromEvent` throws an `Error` exception if the layer has no renderer + +[prev]: https://github.com/openlayers/openlayers/commit/6e9a3e4c13e00c29daf28efd92b63c2390e69231 + +## Changes in formats WMTSCapabilities and SOSCapabilities + +The structure of the object returned by `Format.WMTSCapabilities:read` and `Format.SOSCapabilities:read` has slightly changed. + +For `WMTSCapabilities` the GET href used to be made available at `operationsMetadata.GetCapabilities.dcp.http.get`, the latter is now an array of objects with two properties: `url` and `constrains`. People using `operationsMetadata.GetCapabilities.dcp.http.get` in their applications should certainly use `operationsMetadata.GetCapabilities.dcp.http.get[0].url`. + +Likewise for `SOSCapabilities`. + +Looking at the tests is a good way to understand what the requires changes are. See [SOSCapabilities/v1_0_0.html](https://github.com/openlayers/openlayers/blob/master/tests/Format/SOSCapabilities/v1_0_0.html) and [WMTSCapabilities/v1_0_0.html](https://github.com/openlayers/openlayers/blob/master/tests/Format/WMTSCapabilities/v1_0_0.html). + + * Trac ticket: http://trac.osgeo.org/openlayers/ticket/3568 + * GitHub issue: https://github.com/openlayers/openlayers/pull/40 + + +## Rico deprecation + +We are deprecating the Rico classes/objects in OpenLayers. This has the following implications: + + } + # Behavior Changes from Past Releases ## Function return values From d4249960e336aa3aa97da850b5167beea85219c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 3 Jan 2012 08:29:40 +0100 Subject: [PATCH 21/25] remove duplications in the 2.12 notes --- notes/2.12.md | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/notes/2.12.md b/notes/2.12.md index 42f2ce0e7d..d94c39bfea 100644 --- a/notes/2.12.md +++ b/notes/2.12.md @@ -49,41 +49,6 @@ Looking at the tests is a good way to understand what the requires changes are. * GitHub issue: https://github.com/openlayers/openlayers/pull/40 -## Rico deprecation - -We are deprecating the Rico classes/objects in OpenLayers. This has the following implications: - - } - -# Behavior Changes from Past Releases - -## Function return values - -[Previously][prev] a few functions in the library displayed error messages and returned `undefined`, `null` or `false` if the parameters passed in were bad. In 2.12 these functions now just throw an error/exception. People relying on return values to know if a function call is successful may need to change their code. Here are the modified functions: - - * `OpenLayers.Bounds.add` throws a `TypeError` exception if `x` or `y` is null - * `OpenLayers.LonLat.add` throws a `TypeError` exception if `lon` or `lat` is null - * `OpenLayers.Pixel.add` throws a `TypeError` exception if `x` or `y` is null - * `OpenLayers.Filter.Comparison.value2regex` throws an `Error` exception if `wildcard` equals to `"."` - * `OpenLayers.Layer.PointTrack.addNodes` throws a `TypeError` exception if `endPoint` isn't actually a point - * `OpenLayers.Layer.Vector.getFeatureFromEvent` throws an `Error` exception if the layer has no renderer - -[prev]: https://github.com/openlayers/openlayers/commit/6e9a3e4c13e00c29daf28efd92b63c2390e69231 - -## Changes in formats WMTSCapabilities and SOSCapabilities - -The structure of the object returned by `Format.WMTSCapabilities:read` and `Format.SOSCapabilities:read` has slightly changed. - -For `WMTSCapabilities` the GET href used to be made available at `operationsMetadata.GetCapabilities.dcp.http.get`, the latter is now an array of objects with two properties: `url` and `constrains`. People using `operationsMetadata.GetCapabilities.dcp.http.get` in their applications should certainly use `operationsMetadata.GetCapabilities.dcp.http.get[0].url`. - -Likewise for `SOSCapabilities`. - -Looking at the tests is a good way to understand what the requires changes are. See [SOSCapabilities/v1_0_0.html](https://github.com/openlayers/openlayers/blob/master/tests/Format/SOSCapabilities/v1_0_0.html) and [WMTSCapabilities/v1_0_0.html](https://github.com/openlayers/openlayers/blob/master/tests/Format/WMTSCapabilities/v1_0_0.html). - - * Trac ticket: http://trac.osgeo.org/openlayers/ticket/3568 - * GitHub issue: https://github.com/openlayers/openlayers/pull/40 - - ## Rico deprecation We are deprecating the Rico classes/objects in OpenLayers. This has the following implications: From 39f2ddccee4bf772178cc39cca7e270c64153742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Wed, 4 Jan 2012 08:20:11 +0100 Subject: [PATCH 22/25] remove back buffer immediately in applyBackBuffer if back buffer is schedule for removal --- lib/OpenLayers/Layer/Grid.js | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/lib/OpenLayers/Layer/Grid.js b/lib/OpenLayers/Layer/Grid.js index 976eb674ef..a960b5f288 100644 --- a/lib/OpenLayers/Layer/Grid.js +++ b/lib/OpenLayers/Layer/Grid.js @@ -459,6 +459,9 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { * resolution - {Number} The resolution to transition to. */ applyBackBuffer: function(resolution) { + if(this.backBufferTimerId !== null) { + this.removeBackBuffer(); + } var backBuffer = this.backBuffer; if(!backBuffer) { backBuffer = this.createBackBuffer(); @@ -534,24 +537,17 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { * Remove back buffer from DOM. */ removeBackBuffer: function() { - if(this.backBuffer && this.backBuffer.parentNode) { + if(this.backBuffer) { this.div.removeChild(this.backBuffer); this.backBuffer = null; this.backBufferResolution = null; + if(this.backBufferTimerId !== null) { + window.clearTimeout(this.backBufferTimerId); + this.backBufferTimerId = null; + } } }, - /** - * Method: scheduleBackBufferRemoval - */ - scheduleBackBufferRemoval: function() { - if(this.backBufferTimerId !== null) { - window.clearTimeout(this.backBufferTimerId); - } - this.backBufferTimerId = window.setTimeout( - OpenLayers.Function.bind(this.removeBackBuffer, this), 2500); - }, - /** * Method: moveByPx * Move the layer based on pixel vector. @@ -955,7 +951,10 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { if(this.backBuffer) { // the removal of the back buffer is delayed to prevent flash // effects due to the animation of tile displaying - this.scheduleBackBufferRemoval(); + this.backBufferTimerId = window.setTimeout( + OpenLayers.Function.bind(this.removeBackBuffer, this), + 2500 + ); } } }; From 77f227ffedf4a0587e7ac395aed42ef56766d67f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Wed, 4 Jan 2012 21:01:46 +0100 Subject: [PATCH 23/25] more Grid tests, for delayed back buffer removal --- tests/Layer/Grid.html | 74 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/tests/Layer/Grid.html b/tests/Layer/Grid.html index eae762735c..50d64768d9 100644 --- a/tests/Layer/Grid.html +++ b/tests/Layer/Grid.html @@ -949,7 +949,7 @@ } function test_applyBackBuffer(t) { - t.plan(13); + t.plan(16); var map = new OpenLayers.Map('map2'); var layer = new OpenLayers.Layer.WMS('', '', {}, { @@ -1012,6 +1012,24 @@ t.eq(layer.backBuffer.style.top, '295%', 'back buffer has correct top'); + // test #4 + // and a back buffer in the layer and do as if back buffer removal + // has been scheduled, and test that applyBackBuffer removes the + // back buffer and clears the timer + layer.createBackBuffer = function() { + return; + }; + backBuffer = document.createElement('div'); + layer.div.insertBefore(backBuffer, layer.div.firstChild); + layer.backBuffer = backBuffer; + layer.backBufferTimerId = 'fake'; + layer.applyBackBuffer(2); + t.ok(backBuffer.parentNode !== layer.div, + 'back buffer is not child node of layer div'); + t.eq(layer.backBuffer, null, + 'back buffer not set in layer'); + t.eq(layer.backBufferTimerId, null, + 'back buffer timer cleared'); map.destroy(); } @@ -1058,7 +1076,7 @@ } function test_removeBackBuffer(t) { - t.plan(3); + t.plan(4); var map = new OpenLayers.Map('map'); var layer = new OpenLayers.Layer.WMS('', '', {}, {isBaseLayer: true}); @@ -1070,12 +1088,17 @@ layer.div.appendChild(backBuffer); layer.backBufferResolution = 32; + // add a fake back buffer removal timer + layer.backBufferTimerId = 'fake'; + layer.removeBackBuffer(); t.eq(layer.backBuffer, null, 'backBuffer set to null in layer'); t.eq(layer.backBufferResolution, null, 'backBufferResolution set to null in layer'); t.ok(backBuffer.parentNode !== layer.div, 'back buffer removed from layer'); + t.eq(layer.backBufferTimerId, null, + 'backBufferTimerId set to null in layer'); map.destroy(); } @@ -1215,6 +1238,53 @@ map.destroy(); } + + function test_delayed_back_buffer_removal(t) { + + // + // Test that the delaying of the back buffer removal behaves + // as expected. + // + + t.plan(5); + + // set up + + var map = new OpenLayers.Map('map', { + resolutions: [32, 16, 8, 4, 2, 1] + }); + var layer = new OpenLayers.Layer.WMS('', '', {}, { + isBaseLayer: true, + transitionEffect: 'resize' + }); + map.addLayer(layer); + map.setCenter(new OpenLayers.LonLat(0, 0), 0); + + map.zoomTo(1); + + t.delay_call(1, function() { + + t.ok(layer.backBuffer.parentNode === layer.div, + '[a] back buffer is a child of layer div'); + t.ok(layer.backBufferTimerId !== null, + '[a] back buffer scheduled for removal'); + + var backBuffer = layer.backBuffer; + + map.zoomTo(2); + + t.ok(layer.backBuffer !== backBuffer, + '[b] a new back buffer was created'); + t.ok(layer.backBuffer.parentNode === layer.div, + '[b] back buffer is a child of layer div'); + t.ok(layer.backBufferTimerId === null, + '[b] back buffer no longer scheduled for removal'); + + // tear down + + map.destroy(); + }); + } From f65bc5e764e6e5e99fe170262a38ad5d2a61db87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Thu, 5 Jan 2012 09:36:47 +0100 Subject: [PATCH 24/25] correct css accessor for tile animation in style.mobile.css --- examples/style.mobile.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/style.mobile.css b/examples/style.mobile.css index f5c61ab0ac..58dee4586b 100644 --- a/examples/style.mobile.css +++ b/examples/style.mobile.css @@ -23,7 +23,7 @@ div.olControlZoomPanel .olControlZoomOutItemInactive { top: 72px; background-position: 0 -72px; } -.olMapTileAnim .olTileImage { +.olTileImage { -webkit-transition: opacity 0.2s linear; -moz-transition: opacity 0.2s linear; -o-transition: opacity 0.2s linear; From d3db3011a32d6fb5f9b63b63e582f46643606b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 10 Jan 2012 21:24:09 +0100 Subject: [PATCH 25/25] in Tile.Image do the opacity filter setting where it was done before, i.e. right after the img creation --- lib/OpenLayers/Tile/Image.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/OpenLayers/Tile/Image.js b/lib/OpenLayers/Tile/Image.js index 6ccf1f0b25..d863d7dece 100644 --- a/lib/OpenLayers/Tile/Image.js +++ b/lib/OpenLayers/Tile/Image.js @@ -245,6 +245,11 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { } style.visibility = "hidden"; style.opacity = 0; + if (this.layer.opacity < 1) { + style.filter = 'alpha(opacity=' + + (this.layer.opacity * 100) + + ')'; + } style.position = "absolute"; if (this.layerAlphaHack) { // move the image out of sight @@ -309,7 +314,6 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { var img = this.imgDiv; img.style.visibility = 'hidden'; img.style.opacity = 0; - img.style.filter = 'alpha(opacity=0)'; if (url) { img.src = url; } @@ -361,7 +365,6 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { img.style.visibility = 'inherit'; img.style.opacity = this.layer.opacity; - img.style.filter = 'alpha(opacity=' + (this.layer.opacity * 100) + ')'; this.isLoading = false; this.events.triggerEvent("loadend");