Accept a render callback for state generation

The map's render method can accept a callback that serves as a state generator.  This callback will be called before rendering.  Any changes to the map state can be made before rendering takes place (multiple changes will not result in multiple renders).  The return from this callback indicates whether the generator is exhausted.
This commit is contained in:
Tim Schaub
2012-10-18 00:09:48 -04:00
parent f3b7c2384d
commit fc6f12d5cd
5 changed files with 64 additions and 23 deletions

View File

@@ -635,9 +635,18 @@ ol.Map.prototype.recalculateTransforms_ = function() {
/**
* Render the map.
* @param {Function|boolean=} opt_callback Function to be called immediately
* before the map is rendered. For renderers that are able to perform
* animations this callback can be used to set various map properties
* without incurring multiple repaints. If the callback returns true,
* another rendering will be scheduled. In this way, the callback works as
* a state generator for an animation. Subsequent calls to render can
* replace or remove this callback (if render is called with no callback).
* If render is called with a boolean, this will retain any pending callback
* (if true) or cancel the pending callback (if false).
*/
ol.Map.prototype.render = function() {
this.renderer_.render();
ol.Map.prototype.render = function(opt_callback) {
this.renderer_.render(opt_callback);
};

View File

@@ -92,7 +92,8 @@ ol.renderer.dom.TileLayer.prototype.removeExtraTiles_ =
*/
ol.renderer.dom.TileLayer.prototype.handleTileChange_ = function(event) {
goog.asserts.assert(event.target.getState() == ol.TileState.LOADED);
this.getMap().render();
// do not cancel any pending callback
this.getMapRenderer().render(true);
};

View File

@@ -29,6 +29,24 @@ ol.renderer.Map = function(container, map) {
*/
this.map = map;
/**
* @private
* @type {Function}
*/
this.callback_ = null;
/**
* @private
* @type {boolean}
*/
this.rendering_ = false;
/**
* @private
* @type {boolean}
*/
this.pendingRender_ = false;
/**
* @protected
* @type {Object.<number, ol.renderer.Layer>}
@@ -72,14 +90,6 @@ ol.renderer.Map = function(container, map) {
this.renderFrame, null, this);
this.registerDisposable(this.delayedRender_);
/**
* Flag to indicate whether this.delayedRender_.start has been called.
*
* @type {boolean}
* @private
*/
this.pendingRender_ = false;
/**
* @private
* @type {Array.<number>}
@@ -129,6 +139,7 @@ ol.renderer.Map.prototype.addLayer = function(layer) {
* @protected
*/
ol.renderer.Map.prototype.afterRenderFrame = function() {
this.rendering_ = false;
this.map.dispatchEvent(ol.MapEventType.POSTRENDER);
};
@@ -138,7 +149,20 @@ ol.renderer.Map.prototype.afterRenderFrame = function() {
* @protected
*/
ol.renderer.Map.prototype.beforeRenderFrame = function() {
this.rendering_ = true;
var rerender = false;
if (!goog.isNull(this.callback_)) {
// allow state to be set before rendering
rerender = !!this.callback_();
}
this.pendingRender_ = false;
if (rerender) {
// schedule another rendering
this.render();
} else {
// remove any exhausted callback
this.callback_ = null;
}
};
@@ -346,9 +370,16 @@ ol.renderer.Map.prototype.removeLayerRenderer = function(layer) {
/**
* Render.
* Render the map.
* @param {Function|boolean=} opt_callback Optional callback. See the
* ol.Map.prototype#render method for a description of this callback.
*/
ol.renderer.Map.prototype.render = function() {
ol.renderer.Map.prototype.render = function(opt_callback) {
if (!this.rendering_ && opt_callback !== true) {
// we only replace the callback during calls to render that are
// not triggered during a rendering
this.callback_ = /** @type {Function} */ opt_callback || null;
}
if (!this.pendingRender_ && this.getMap().isDef()) {
this.pendingRender_ = true;
this.delayedRender_.start();

View File

@@ -251,7 +251,7 @@ goog.inherits(ol.renderer.webgl.Map, ol.renderer.Map);
ol.renderer.webgl.Map.prototype.addLayer = function(layer) {
goog.base(this, 'addLayer', layer);
if (layer.getVisible()) {
this.getMap().render();
this.render();
}
};
@@ -417,7 +417,7 @@ ol.renderer.webgl.Map.prototype.handleBackgroundColorChanged = function() {
backgroundColor.g / 255,
backgroundColor.b / 255,
backgroundColor.a / 255);
this.getMap().render();
this.render();
};
@@ -426,7 +426,7 @@ ol.renderer.webgl.Map.prototype.handleBackgroundColorChanged = function() {
*/
ol.renderer.webgl.Map.prototype.handleCenterChanged = function() {
goog.base(this, 'handleCenterChanged');
this.getMap().render();
this.render();
};
@@ -435,7 +435,7 @@ ol.renderer.webgl.Map.prototype.handleCenterChanged = function() {
* @protected
*/
ol.renderer.webgl.Map.prototype.handleLayerRendererChange = function(event) {
this.getMap().render();
this.render(true);
};
@@ -444,7 +444,7 @@ ol.renderer.webgl.Map.prototype.handleLayerRendererChange = function(event) {
*/
ol.renderer.webgl.Map.prototype.handleResolutionChanged = function() {
goog.base(this, 'handleResolutionChanged');
this.getMap().render();
this.render();
};
@@ -453,7 +453,7 @@ ol.renderer.webgl.Map.prototype.handleResolutionChanged = function() {
*/
ol.renderer.webgl.Map.prototype.handleRotationChanged = function() {
goog.base(this, 'handleRotationChanged');
this.getMap().render();
this.render();
};
@@ -462,7 +462,7 @@ ol.renderer.webgl.Map.prototype.handleRotationChanged = function() {
*/
ol.renderer.webgl.Map.prototype.handleSizeChanged = function() {
goog.base(this, 'handleSizeChanged');
this.getMap().render();
this.render();
};
@@ -494,7 +494,7 @@ ol.renderer.webgl.Map.prototype.handleWebGLContextResourced = function() {
this.logger.info('WebGLContextResourced');
}
this.initializeGL_();
this.getMap().render();
this.render();
};
@@ -526,7 +526,7 @@ ol.renderer.webgl.Map.prototype.isImageTextureLoaded = function(image) {
ol.renderer.webgl.Map.prototype.removeLayer = function(layer) {
goog.base(this, 'removeLayer', layer);
if (layer.getVisible()) {
this.getMap().render();
this.render();
}
};

View File

@@ -527,7 +527,7 @@ ol.renderer.webgl.TileLayer.prototype.render = function() {
0);
if (rerender) {
mapRenderer.render();
mapRenderer.render(true);
}
};