Merge pull request #3305 from bartvde/image-load-events
Add image loading events to image sources (r=@ahocevar,@elemoine)
This commit is contained in:
79
examples/image-load-events.html
Normal file
79
examples/image-load-events.html
Normal file
@@ -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
examples/image-load-events.js
Normal file
105
examples/image-load-events.js
Normal file
@@ -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
|
||||
})
|
||||
});
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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');
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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.
|
||||
@@ -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'
|
||||
|
||||
};
|
||||
|
||||
@@ -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');
|
||||
@@ -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
|
||||
@@ -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_;
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user