diff --git a/src/all.js b/src/all.js index cd57d0dd57..14180a12a5 100644 --- a/src/all.js +++ b/src/all.js @@ -8,6 +8,7 @@ goog.require('ol.Layer'); goog.require('ol.Object'); goog.require('ol.Projection'); goog.require('ol.Store'); +goog.require('ol.Tile'); goog.require('ol.TileBounds'); goog.require('ol.TileCoord'); goog.require('ol.TileGrid'); diff --git a/src/ol/Tile.js b/src/ol/Tile.js deleted file mode 100644 index 8e9c7a7cc2..0000000000 --- a/src/ol/Tile.js +++ /dev/null @@ -1,172 +0,0 @@ -goog.provide('ol.Tile'); - -goog.require('goog.events'); -goog.require('goog.asserts'); -goog.require('ol.Bounds'); -goog.require('ol.event.Events'); - -/** - * The Tile class. - * @constructor - * @param {string} url - * @param {ol.Bounds|undefined} opt_bounds - */ -ol.Tile = function(url, opt_bounds) { - - /** - * @private - * @type {string} - */ - this.url_ = url; - - /** - * @private - * @type {ol.Bounds|undefined} - */ - this.bounds_ = opt_bounds; - - /** - * @private - * @type {boolean} - */ - this.loaded_ = false; - - /** - * @private - * @type {boolean} - */ - this.loading_ = false; - - /** - * @private - * @type {HTMLImageElement} - */ - this.img_ = this.createImage(); - goog.events.listenOnce(this.img_, goog.events.EventType.LOAD, - this.handleImageLoad, false, this); - goog.events.listenOnce(this.img_, goog.events.EventType.ERROR, - this.handleImageError, false, this); - - /** - * @private - * @type {ol.event.Events} - */ - this.events_ = new ol.event.Events(this); -}; - -/** - * @protected - * @return {HTMLImageElement} - */ -ol.Tile.prototype.createImage = function() { - // overriden by subclasses -}; - -/** - * Load the tile. A tile should loaded only once. - */ -ol.Tile.prototype.load = function() { - goog.asserts.assert(!this.loaded_ && !this.loading_); - this.loading_ = true; - this.img_.src = this.url_; -}; - -/** - * Get the tile url. - * @return {string} - */ -ol.Tile.prototype.getUrl = function() { - return this.url_; -}; - -/** - * Get the tile bounds. - * @return {ol.Bounds|undefined} - */ -ol.Tile.prototype.getBounds = function() { - return this.bounds_; -}; - -/** - * Get the tile image. - * @return {HTMLImageElement} - */ -ol.Tile.prototype.getImg = function() { - return this.img_; -}; - -/** - * Handle load event on the image. - * @param {goog.events.BrowserEvent} evt Event. - */ -ol.Tile.prototype.handleImageLoad = function(evt) { - this.loading_ = false; - this.loaded_ = true; - this.img_.style.visibility = "inherit"; - this.img_.style.opacity = 1; // TODO: allow for layer opacity - this.events_.triggerEvent('load'); -}; - -/** - * Handle load error event on the image. - * @param {goog.events.BrowserEvent} evt Event. - */ -ol.Tile.prototype.handleImageError = function(evt) { - this.loading_ = false; - this.events_.triggerEvent('error'); -}; - -/** - * Is the tile loaded already? - * @return {boolean} - */ -ol.Tile.prototype.isLoaded = function() { - return this.loaded_; -}; - -/** - * Is the tile being loaded? - * @return {boolean} - */ -ol.Tile.prototype.isLoading = function() { - return this.loading_; -}; - -/** - * - */ -ol.Tile.prototype.destroy = function() { - this.events_.triggerEvent('destroy'); -}; - -/** - * Create a tile constructor, for specific width and height values - * for the tiles. - * @param {number} width - * @param {number} height - * @return {function(new:ol.Tile, string, ol.Bounds=)} - */ -ol.Tile.createConstructor = function(width, height) { - /** - * @constructor - * @extends {ol.Tile} - */ - var Tile = function(url, opt_bounds) { - goog.base(this, url, opt_bounds); - }; - goog.inherits(Tile, ol.Tile); - /** @inheritDoc */ - Tile.prototype.createImage = (function() { - var img = document.createElement("img"); - img.className = "olTile"; - img.style.position = "absolute"; - img.style.width = width + "px"; - img.style.height = height + "px"; - img.style.opacity = 0; - img.src = "data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="; - return function() { - return img.cloneNode(false); - }; - })(); - return Tile; -}; diff --git a/src/ol/tile.js b/src/ol/tile.js new file mode 100644 index 0000000000..598651f9fc --- /dev/null +++ b/src/ol/tile.js @@ -0,0 +1,129 @@ +goog.provide('ol.Tile'); + +goog.require('goog.events'); +goog.require('goog.events.EventTarget'); +goog.require('goog.events.EventType'); +goog.require('ol.TileCoord'); + + +/** + * @enum {number} + */ +ol.TileLoadState = { + IDLE: 0, + LOADING: 1, + LOADED: 2, + ERROR: 3 +}; + + + +/** + * @constructor + * @extends {goog.events.EventTarget} + * @param {ol.TileCoord} tileCoord Tile coordinate. + * @param {string} src Source. + * @param {string=} opt_crossOrigin Cross origin. + */ +ol.Tile = function(tileCoord, src, opt_crossOrigin) { + + goog.base(this); + + /** + * @type {ol.TileCoord} + */ + this.tileCoord = tileCoord; + + /** + * @private + * @type {string} + */ + this.src_ = src; + + /** + * @private + * @type {ol.TileLoadState} + */ + this.state_ = ol.TileLoadState.IDLE; + + /** + * @private + * @type {Image} + */ + this.image_ = new Image(); + if (goog.isDef(opt_crossOrigin)) { + this.image_.crossOrigin = opt_crossOrigin; + } + + /** + * @private + * @type {Array.} + */ + this.imageListenerKeys_ = null; + +}; +goog.inherits(ol.Tile, goog.events.EventTarget); + + +/** + * @return {Image} Image. + */ +ol.Tile.prototype.getImage = function() { + return this.image_; +}; + + +/** + * @private + */ +ol.Tile.prototype.handleImageError_ = function() { + this.state_ = ol.TileLoadState.ERROR; + this.unlistenImage_(); +}; + + +/** + * @private + */ +ol.Tile.prototype.handleImageLoad_ = function() { + this.state_ = ol.TileLoadState.LOADED; + this.unlistenImage_(); +}; + + +/** + * @return {boolean} Is loaded. + */ +ol.Tile.prototype.isLoaded = function() { + return this.state_ == ol.TileLoadState.LOADED; +}; + + +/** + * @return {EventTarget} Event target. + */ +ol.Tile.prototype.load = function() { + if (this.state_ == ol.TileLoadState.IDLE) { + this.state_ = ol.TileLoadState.LOADING; + goog.asserts.assert(goog.isNull(this.imageListenerKeys_)); + this.imageListenerKeys_ = [ + goog.events.listenOnce(this.image_, goog.events.EventType.ERROR, + this.handleImageError_, false, this), + goog.events.listenOnce(this.image_, goog.events.EventType.LOAD, + this.handleImageLoad_, false, this) + ]; + this.image_.src = this.src_; + } + return this.image_; +}; + + +/** + * @private + */ +ol.Tile.prototype.unlistenImage_ = function() { + goog.asserts.assert(!goog.isNull(this.imageListenerKeys_)); + goog.array.forEach(this.imageListenerKeys_, goog.events.unlistenByKey); + this.imageListenerKeys_ = null; +}; +