From 7e5e221c8dd510345d62f46ea1e372afa93693e8 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Fri, 5 Oct 2012 09:24:53 +0200 Subject: [PATCH] Image loading performance improvements Performance improvements are achieved by using requestAnimationFrame when a tile's visibility changes, and by not starting with a blank image when creating a new tile image. It seems that even Firefox does not show a loading placeholder when the tile is made visible in an animation. --- lib/OpenLayers/Tile/Image.js | 63 +++++++++++++++++------------------- tests/Tile/Image.html | 4 ++- 2 files changed, 32 insertions(+), 35 deletions(-) diff --git a/lib/OpenLayers/Tile/Image.js b/lib/OpenLayers/Tile/Image.js index e3c412a8ed..cd7ec67728 100644 --- a/lib/OpenLayers/Tile/Image.js +++ b/lib/OpenLayers/Tile/Image.js @@ -232,7 +232,6 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { OpenLayers.Tile.prototype.clear.apply(this, arguments); var img = this.imgDiv; if (img) { - OpenLayers.Event.stopObservingElement(img); var tile = this.getTile(); if (tile.parentNode === this.layer.div) { this.layer.div.removeChild(tile); @@ -252,11 +251,7 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { */ getImage: function() { if (!this.imgDiv) { - this.imgDiv = document.createElement("img"); - - this.imgDiv.className = "olTileImage"; - // avoid image gallery menu in IE6 - this.imgDiv.galleryImg = "no"; + this.imgDiv = OpenLayers.Tile.Image.IMAGE.cloneNode(false); var style = this.imgDiv.style; if (this.frame) { @@ -302,36 +297,20 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { if (this.url && img.getAttribute("src") == this.url) { this.onImageLoad(); } else { - // We need to start with a blank image, to make sure that no - // loading image placeholder and no old image is displayed when we - // set the display style to "" in onImageLoad, which is called - // after the image is loaded, but before it is rendered. So we set - // a blank image with a data scheme URI, and register for the load - // event (for browsers that support data scheme) and the error - // event (for browsers that don't). In the event handler, we set - // the final src. - var load = OpenLayers.Function.bind(function() { + if (img.getAttribute("src") !== this.blankImageUrl) { OpenLayers.Event.stopObservingElement(img); - OpenLayers.Event.observe(img, "load", - OpenLayers.Function.bind(this.onImageLoad, this) - ); - OpenLayers.Event.observe(img, "error", - OpenLayers.Function.bind(this.onImageError, this) - ); - this.imageReloadAttempts = 0; - this.setImgSrc(this.url); - }, this); - if (img.getAttribute("src") == this.blankImageUrl) { - load(); - } else { - OpenLayers.Event.stopObservingElement(img); - OpenLayers.Event.observe(img, "load", load); - OpenLayers.Event.observe(img, "error", load); if (this.crossOriginKeyword) { img.removeAttribute("crossorigin"); } - img.src = this.blankImageUrl; } + OpenLayers.Event.observe(img, "load", + OpenLayers.Function.bind(this.onImageLoad, this) + ); + OpenLayers.Event.observe(img, "error", + OpenLayers.Function.bind(this.onImageError, this) + ); + this.imageReloadAttempts = 0; + this.setImgSrc(this.url); } }, @@ -359,6 +338,7 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { } else { // Remove reference to the image, and leave it to the browser's // caching and garbage collection. + OpenLayers.Event.stopObservingElement(this.imgDiv); this.imgDiv = null; if (img.parentNode) { img.parentNode.removeChild(img); @@ -410,12 +390,14 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { var img = this.imgDiv; OpenLayers.Event.stopObservingElement(img); - img.style.visibility = 'inherit'; - img.style.opacity = this.layer.opacity; + OpenLayers.Animation.requestFrame(OpenLayers.Function.bind(function() { + img.style.visibility = 'inherit'; + img.style.opacity = this.layer.opacity; + this.events.triggerEvent("loadend"); + }, this)); this.isLoading = false; this.canvasContext = null; - this.events.triggerEvent("loadend"); if (this.layerAlphaHack === true) { img.style.filter = @@ -477,3 +459,16 @@ OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { CLASS_NAME: "OpenLayers.Tile.Image" }); + +/** + * Constant: OpenLayers.Tile.Image.IMAGE + * {HTMLImageElement} The image for a tile. + */ +OpenLayers.Tile.Image.IMAGE = (function() { + var img = new Image(); + img.className = "olTileImage"; + // avoid image gallery menu in IE6 + img.galleryImg = "no"; + return img; +}()); + diff --git a/tests/Tile/Image.html b/tests/Tile/Image.html index d2e48cc191..30ff1f1d18 100644 --- a/tests/Tile/Image.html +++ b/tests/Tile/Image.html @@ -2,8 +2,10 @@