diff --git a/examples/tile-load-events.html b/examples/tile-load-events.html new file mode 100644 index 0000000000..4bea910614 --- /dev/null +++ b/examples/tile-load-events.html @@ -0,0 +1,51 @@ + + + + + + + + + + + Tile load events example + + + + + +
+ +
+
+
+
+
+ +
+ +
+

Tile load events example

+

Example using tile load events.

+
+

See the tile-load-events.js source to see how this is done.

+
+
tile, events, loading
+
+ +
+ +
+ + + + + + + diff --git a/examples/tile-load-events.js b/examples/tile-load-events.js new file mode 100644 index 0000000000..ea00420993 --- /dev/null +++ b/examples/tile-load-events.js @@ -0,0 +1,35 @@ +goog.require('ol.Map'); +goog.require('ol.View'); +goog.require('ol.control'); +goog.require('ol.layer.Tile'); +goog.require('ol.source.OSM'); + + +var source = new ol.source.OSM(); +source.on('tileloadstart', function(event) { + console.log('start', event.tile.getImage().src); +}); +source.on('tileloadend', function(event) { + console.log('end', event.tile.getImage().src); +}); +source.on('tileloaderror', function(event) { + console.log('error', event.tile.getImage().src); +}); + + +var map = new ol.Map({ + layers: [ + new ol.layer.Tile({source: source}) + ], + controls: ol.control.defaults({ + attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ + collapsible: false + }) + }), + renderer: exampleNS.getRendererFromQueryString(), + target: 'map', + view: new ol.View({ + center: [0, 0], + zoom: 2 + }) +}); diff --git a/externs/oli.js b/externs/oli.js index 9ffb8877f3..a97117e207 100644 --- a/externs/oli.js +++ b/externs/oli.js @@ -210,6 +210,17 @@ oli.render.Event.prototype.vectorContext; oli.source; +/** + * @interface + */ +oli.source.TileEvent = function() {}; + + +/** + * @type {ol.Tile} + */ +oli.source.TileEvent.prototype.tile; + /** * @interface diff --git a/src/ol/source/tileimagesource.js b/src/ol/source/tileimagesource.js index 600eb69313..1e53f22d10 100644 --- a/src/ol/source/tileimagesource.js +++ b/src/ol/source/tileimagesource.js @@ -1,6 +1,8 @@ goog.provide('ol.source.TileImage'); goog.require('goog.asserts'); +goog.require('goog.events'); +goog.require('goog.events.EventType'); goog.require('ol.ImageTile'); goog.require('ol.TileCache'); goog.require('ol.TileCoord'); @@ -17,6 +19,7 @@ goog.require('ol.source.Tile'); * Base class for sources providing images divided into a tile grid. * * @constructor + * @fires ol.source.TileEvent * @extends {ol.source.Tile} * @param {olx.source.TileImageOptions} options Image tile options. * @api @@ -118,6 +121,9 @@ ol.source.TileImage.prototype.getTile = goog.isDef(tileUrl) ? tileUrl : '', this.crossOrigin, this.tileLoadFunction); + goog.events.listen(tile, goog.events.EventType.CHANGE, + this.handleTileChange_, false, this); + this.tileCache.set(tileCoordKey, tile); return tile; } @@ -142,6 +148,30 @@ ol.source.TileImage.prototype.getTileUrlFunction = function() { }; +/** + * Handle tile change events. + * @param {goog.events.Event} event Event. + * @private + */ +ol.source.TileImage.prototype.handleTileChange_ = function(event) { + var tile = /** @type {ol.Tile} */ (event.target); + switch (tile.getState()) { + case ol.TileState.LOADING: + this.dispatchEvent( + new ol.source.TileEvent(ol.source.TileEventType.TILELOADSTART, tile)); + break; + case ol.TileState.LOADED: + this.dispatchEvent( + new ol.source.TileEvent(ol.source.TileEventType.TILELOADEND, tile)); + break; + case ol.TileState.ERROR: + this.dispatchEvent( + new ol.source.TileEvent(ol.source.TileEventType.TILELOADERROR, tile)); + break; + } +}; + + /** * @param {ol.TileLoadFunctionType} tileLoadFunction Tile load function. * @api diff --git a/src/ol/source/tilesource.js b/src/ol/source/tilesource.js index 3457b4cb13..504910ae84 100644 --- a/src/ol/source/tilesource.js +++ b/src/ol/source/tilesource.js @@ -1,6 +1,7 @@ goog.provide('ol.source.Tile'); goog.provide('ol.source.TileOptions'); +goog.require('goog.events.Event'); goog.require('goog.functions'); goog.require('ol.Attribution'); goog.require('ol.Extent'); @@ -206,3 +207,59 @@ ol.source.Tile.prototype.getTilePixelSize = * @param {number} y Tile coordinate y. */ ol.source.Tile.prototype.useTile = goog.nullFunction; + + + +/** + * @classdesc + * Events emitted by {@link ol.source.Tile} instances are instances of this + * type. + * + * @constructor + * @extends {goog.events.Event} + * @implements {oli.source.TileEvent} + * @param {string} type Type. + * @param {ol.Tile} tile The tile. + */ +ol.source.TileEvent = function(type, tile) { + + goog.base(this, type); + + /** + * The tile related to the event. + * @type {ol.Tile} + * @api + */ + this.tile = tile; + +}; +goog.inherits(ol.source.TileEvent, goog.events.Event); + + +/** + * @enum {string} + */ +ol.source.TileEventType = { + + /** + * Triggered when a tile starts loading. + * @event ol.source.TileEvent#tileloadstart + * @api + */ + TILELOADSTART: 'tileloadstart', + + /** + * Triggered when a tile finishes loading. + * @event ol.source.TileEvent#tileloadend + * @api + */ + TILELOADEND: 'tileloadend', + + /** + * Triggered if tile loading results in an error. + * @event ol.source.TileEvent#tileloaderror + * @api + */ + TILELOADERROR: 'tileloaderror' + +};