Skip to content

Commit

Permalink
Merge pull request openlayers#3305 from bartvde/image-load-events
Browse files Browse the repository at this point in the history
Add image loading events to image sources (r=@ahocevar,@elemoine)
  • Loading branch information
bartvde committed Mar 17, 2015
2 parents 3a7b975 + 4569858 commit 8061b69
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 1 deletion.
79 changes: 79 additions & 0 deletions examples/image-load-events.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="../css/ol.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap.min.css" type="text/css">
<link rel="stylesheet" href="../resources/layout.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
<title>Image load events example</title>
<style>
.map {
background: #E0ECED;
}
.wrapper {
position: relative;
}
#progress {
position: absolute;
bottom: 0;
left: 0;
height: 2px;
background: rgba(0, 60, 136, 0.4);
width: 0;
transition: width 250ms;
}
</style>
</head>
<body>

<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="./"><img src="../resources/logo.png"> OpenLayers 3 Examples</a>
</div>
</div>
</div>

<div class="container-fluid">

<div class="row-fluid">
<div class="span12 wrapper">
<div id="map" class="map"></div>
<div id="progress"></div>
</div>
</div>

<div class="row-fluid">

<div class="span12">
<h4 id="title">Image load events example</h4>
<p id="shortdesc">Example using image load events.</p>
<div id="docs">
<p>
Image sources fire events related to image loading. You can
listen for <code>imageloadstart</code>, <code>imageloadend</code>,
and <code>imageloaderror</code> type events to monitor image loading
progress. This example registers listeners for these events and
renders an image loading progress bar at the bottom of the map.
</p>
<p>
See the <a href="image-load-events.js" target="_blank">image-load-events.js source</a>
for more detail on how this is done.
</p>
</div>
<div id="tags">image, events, loading</div>
</div>

</div>

</div>

<script src="../resources/jquery.min.js" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
<script src="loader.js?id=image-load-events" type="text/javascript"></script>

</body>
</html>
105 changes: 105 additions & 0 deletions examples/image-load-events.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.layer.Image');
goog.require('ol.source.ImageWMS');



/**
* Renders a progress bar.
* @param {Element} el The target element.
* @constructor
*/
function Progress(el) {
this.el = el;
this.loading = 0;
this.loaded = 0;
}


/**
* Increment the count of loading tiles.
*/
Progress.prototype.addLoading = function() {
if (this.loading === 0) {
this.show();
}
++this.loading;
this.update();
};


/**
* Increment the count of loaded tiles.
*/
Progress.prototype.addLoaded = function() {
setTimeout(function() {
++this.loaded;
this.update();
}.bind(this), 100);
};


/**
* Update the progress bar.
*/
Progress.prototype.update = function() {
var width = (this.loaded / this.loading * 100).toFixed(1) + '%';
this.el.style.width = width;
if (this.loading === this.loaded) {
this.loading = 0;
this.loaded = 0;
setTimeout(this.hide.bind(this), 500);
}
};


/**
* Show the progress bar.
*/
Progress.prototype.show = function() {
this.el.style.visibility = 'visible';
};


/**
* Hide the progress bar.
*/
Progress.prototype.hide = function() {
if (this.loading === this.loaded) {
this.el.style.visibility = 'hidden';
this.el.style.width = 0;
}
};

var progress = new Progress(document.getElementById('progress'));

var source = new ol.source.ImageWMS({
url: 'http://demo.boundlessgeo.com/geoserver/wms',
params: {'LAYERS': 'topp:states'},
serverType: 'geoserver'
});

source.on('imageloadstart', function(event) {
progress.addLoading();
});

source.on('imageloadend', function(event) {
progress.addLoaded();
});
source.on('imageloaderror', function(event) {
progress.addLoaded();
});

var map = new ol.Map({
logo: false,
layers: [
new ol.layer.Image({source: source})
],
renderer: exampleNS.getRendererFromQueryString(),
target: 'map',
view: new ol.View({
center: [-10997148, 4569099],
zoom: 4
})
});
12 changes: 12 additions & 0 deletions externs/oli.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,18 @@ oli.render.Event.prototype.vectorContext;
oli.source;


/**
* @interface
*/
oli.source.ImageEvent = function() {};


/**
* @type {ol.Image}
*/
oli.source.ImageEvent.prototype.image;


/**
* @interface
*/
Expand Down
1 change: 1 addition & 0 deletions src/ol/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ ol.Image.prototype.handleImageLoad_ = function() {
ol.Image.prototype.load = function() {
if (this.state == ol.ImageState.IDLE) {
this.state = ol.ImageState.LOADING;
this.changed();
goog.asserts.assert(goog.isNull(this.imageListenerKeys_));
this.imageListenerKeys_ = [
goog.events.listenOnce(this.image_, goog.events.EventType.ERROR,
Expand Down
2 changes: 1 addition & 1 deletion src/ol/renderer/layerrenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ ol.renderer.Layer.prototype.loadImage = function(image) {
// listener (a noop if the listener was already registered)
goog.asserts.assert(imageState == ol.ImageState.IDLE ||
imageState == ol.ImageState.LOADING);
goog.events.listenOnce(image, goog.events.EventType.CHANGE,
goog.events.listen(image, goog.events.EventType.CHANGE,
this.handleImageChange_, false, this);
}
if (imageState == ol.ImageState.IDLE) {
Expand Down
5 changes: 5 additions & 0 deletions src/ol/source/imagemapguidesource.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
goog.provide('ol.source.ImageMapGuide');

goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.object');
goog.require('goog.uri.utils');
goog.require('ol.Image');
Expand All @@ -15,6 +17,7 @@ goog.require('ol.source.Image');
* Source for images from Mapguide servers
*
* @constructor
* @fires ol.source.ImageEvent
* @extends {ol.source.Image}
* @param {olx.source.ImageMapGuideOptions} options Options.
* @api stable
Expand Down Expand Up @@ -150,6 +153,8 @@ ol.source.ImageMapGuide.prototype.getImage =
image = new ol.Image(extent, resolution, pixelRatio,
this.getAttributions(), imageUrl, this.crossOrigin_,
this.imageLoadFunction_);
goog.events.listen(image, goog.events.EventType.CHANGE,
this.handleImageChange, false, this);
} else {
image = null;
}
Expand Down
85 changes: 85 additions & 0 deletions src/ol/source/imagesource.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ goog.provide('ol.source.Image');

goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.events.Event');
goog.require('ol.Attribution');
goog.require('ol.Extent');
goog.require('ol.ImageState');
goog.require('ol.array');
goog.require('ol.source.Source');

Expand Down Expand Up @@ -90,6 +92,33 @@ ol.source.Image.prototype.findNearestResolution =
ol.source.Image.prototype.getImage = goog.abstractMethod;


/**
* Handle image change events.
* @param {goog.events.Event} event Event.
* @protected
*/
ol.source.Image.prototype.handleImageChange = function(event) {
var image = /** @type {ol.Image} */ (event.target);
switch (image.getState()) {
case ol.ImageState.LOADING:
this.dispatchEvent(
new ol.source.ImageEvent(ol.source.ImageEventType.IMAGELOADSTART,
image));
break;
case ol.ImageState.LOADED:
this.dispatchEvent(
new ol.source.ImageEvent(ol.source.ImageEventType.IMAGELOADEND,
image));
break;
case ol.ImageState.ERROR:
this.dispatchEvent(
new ol.source.ImageEvent(ol.source.ImageEventType.IMAGELOADERROR,
image));
break;
}
};


/**
* Default image load function for image sources that use ol.Image image
* instances.
Expand All @@ -99,3 +128,59 @@ ol.source.Image.prototype.getImage = goog.abstractMethod;
ol.source.Image.defaultImageLoadFunction = function(image, src) {
image.getImage().src = src;
};



/**
* @classdesc
* Events emitted by {@link ol.source.Image} instances are instances of this
* type.
*
* @constructor
* @extends {goog.events.Event}
* @implements {oli.source.ImageEvent}
* @param {string} type Type.
* @param {ol.Image} image The image.
*/
ol.source.ImageEvent = function(type, image) {

goog.base(this, type);

/**
* The image related to the event.
* @type {ol.Image}
* @api
*/
this.image = image;

};
goog.inherits(ol.source.ImageEvent, goog.events.Event);


/**
* @enum {string}
*/
ol.source.ImageEventType = {

/**
* Triggered when an image starts loading.
* @event ol.source.ImageEvent#imageloadstart
* @api
*/
IMAGELOADSTART: 'imageloadstart',

/**
* Triggered when an image finishes loading.
* @event ol.source.ImageEvent#imageloadend
* @api
*/
IMAGELOADEND: 'imageloadend',

/**
* Triggered if image loading results in an error.
* @event ol.source.ImageEvent#imageloaderror
* @api
*/
IMAGELOADERROR: 'imageloaderror'

};
6 changes: 6 additions & 0 deletions src/ol/source/imagewmssource.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
goog.provide('ol.source.ImageWMS');

goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.object');
goog.require('goog.string');
goog.require('goog.uri.utils');
Expand All @@ -22,6 +24,7 @@ goog.require('ol.source.wms.ServerType');
* Source for WMS servers providing single, untiled images.
*
* @constructor
* @fires ol.source.ImageEvent
* @extends {ol.source.Image}
* @param {olx.source.ImageWMSOptions=} opt_options Options.
* @api stable
Expand Down Expand Up @@ -247,6 +250,9 @@ ol.source.ImageWMS.prototype.getImage =

this.renderedRevision_ = this.getRevision();

goog.events.listen(this.image_, goog.events.EventType.CHANGE,
this.handleImageChange, false, this);

return this.image_;

};
Expand Down

0 comments on commit 8061b69

Please sign in to comment.