Leaving animation entirely up to the renderers
With this change, the map knows nothing of animation. Different renderers may behave differently when their render method is called. A PDF renderer (thought experiment at this point) might immediately render to a file. The dom based renderers schedule a repaint for the next animation frame or in a timeout depending on capabilities - in either case, setting multiple map properties will *not* result in multiple reflow/repaints.
This commit is contained in:
@@ -8,7 +8,6 @@ goog.provide('ol.MapProperty');
|
||||
goog.provide('ol.RendererHint');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.async.AnimationDelay');
|
||||
goog.require('goog.debug.Logger');
|
||||
goog.require('goog.dispose');
|
||||
goog.require('goog.dom');
|
||||
@@ -224,27 +223,6 @@ ol.Map = function(mapOptions) {
|
||||
new mapOptionsInternal.rendererConstructor(this.viewport_, this);
|
||||
this.registerDisposable(this.renderer_);
|
||||
|
||||
/**
|
||||
* Calls to this.delayedRender_.start take advantage of requestAnimationFrame
|
||||
* (and friends) where available. The provided listener is called once in
|
||||
* the next available frame after the start method is called. A call to stop
|
||||
* will cancel the animation.
|
||||
*
|
||||
* @type {goog.async.AnimationDelay}
|
||||
* @private
|
||||
*/
|
||||
this.delayedRender_ = new goog.async.AnimationDelay(
|
||||
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
|
||||
*/
|
||||
@@ -656,37 +634,10 @@ ol.Map.prototype.recalculateTransforms_ = function() {
|
||||
|
||||
|
||||
/**
|
||||
* Render the map. Map rendering will be called with requestAnimationFrame
|
||||
* or in a timeout depending on the environment.
|
||||
*
|
||||
* @param {boolean=} opt_force Render immediately. If called with force,
|
||||
* rendering will occur before method returns. If called without force,
|
||||
* method will return before rendering occurs.
|
||||
* Render the map.
|
||||
*/
|
||||
ol.Map.prototype.render = function(opt_force) {
|
||||
if (opt_force) {
|
||||
this.delayedRender_.stop();
|
||||
this.renderFrame_();
|
||||
} else if (!this.pendingRender_) {
|
||||
this.pendingRender_ = true;
|
||||
this.delayedRender_.start();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.Map.prototype.renderFrame_ = function() {
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('renderFrame_');
|
||||
}
|
||||
this.pendingRender_ = false;
|
||||
ol.Map.prototype.render = function() {
|
||||
this.renderer_.render();
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('postrender');
|
||||
}
|
||||
this.dispatchEvent(ol.MapEventType.POSTRENDER);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -135,11 +135,7 @@ ol.renderer.dom.Map.prototype.createLayerRenderer = function(layer) {
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.handleCenterChanged = function() {
|
||||
goog.base(this, 'handleCenterChanged');
|
||||
var map = this.getMap();
|
||||
if (!map.isDef()) {
|
||||
return;
|
||||
}
|
||||
map.render();
|
||||
this.render();
|
||||
};
|
||||
|
||||
|
||||
@@ -148,11 +144,7 @@ ol.renderer.dom.Map.prototype.handleCenterChanged = function() {
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.handleResolutionChanged = function() {
|
||||
goog.base(this, 'handleResolutionChanged');
|
||||
var map = this.getMap();
|
||||
if (!map.isDef()) {
|
||||
return;
|
||||
}
|
||||
map.render();
|
||||
this.render();
|
||||
};
|
||||
|
||||
|
||||
@@ -161,10 +153,7 @@ ol.renderer.dom.Map.prototype.handleResolutionChanged = function() {
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.handleRotationChanged = function() {
|
||||
var map = this.getMap();
|
||||
if (!map.isDef()) {
|
||||
return;
|
||||
}
|
||||
map.render();
|
||||
this.render();
|
||||
};
|
||||
|
||||
|
||||
@@ -173,11 +162,7 @@ ol.renderer.dom.Map.prototype.handleRotationChanged = function() {
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.handleSizeChanged = function() {
|
||||
goog.base(this, 'handleSizeChanged');
|
||||
var map = this.getMap();
|
||||
if (!map.isDef()) {
|
||||
return;
|
||||
}
|
||||
map.render();
|
||||
this.render();
|
||||
};
|
||||
|
||||
|
||||
@@ -185,12 +170,11 @@ ol.renderer.dom.Map.prototype.handleSizeChanged = function() {
|
||||
* Render the map. Sets up the layers pane on first render and adjusts its
|
||||
* position as needed on subsequent calls.
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.render = function() {
|
||||
var map = this.getMap();
|
||||
if (!map.isDef()) {
|
||||
return;
|
||||
}
|
||||
ol.renderer.dom.Map.prototype.renderFrame = function() {
|
||||
|
||||
this.beforeRenderFrame();
|
||||
|
||||
var map = this.getMap();
|
||||
var mapCenter = map.getCenter();
|
||||
var mapSize = map.getSize();
|
||||
var mapResolution = map.getResolution();
|
||||
@@ -226,7 +210,11 @@ ol.renderer.dom.Map.prototype.render = function() {
|
||||
this.renderedRotation_ = mapRotation;
|
||||
this.renderedSize_ = mapSize;
|
||||
|
||||
goog.base(this, 'render');
|
||||
this.forEachReadyVisibleLayer(function(layer, layerRenderer) {
|
||||
layerRenderer.render();
|
||||
});
|
||||
|
||||
this.afterRenderFrame();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -102,9 +102,7 @@ ol.renderer.dom.TileLayer.prototype.handleTileChange_ = function(event) {
|
||||
ol.renderer.dom.TileLayer.prototype.render = function() {
|
||||
|
||||
var map = this.getMap();
|
||||
if (!map.isDef()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var mapExtent = /** @type {!ol.Extent} */ map.getRotatedExtent();
|
||||
var mapResolution = /** @type {number} */ map.getResolution();
|
||||
var resolutionChanged = (mapResolution !== this.renderedMapResolution_);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
goog.provide('ol.renderer.Map');
|
||||
|
||||
goog.require('goog.Disposable');
|
||||
goog.require('goog.async.AnimationDelay');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.vec.Mat4');
|
||||
|
||||
@@ -58,6 +59,27 @@ ol.renderer.Map = function(container, map) {
|
||||
*/
|
||||
this.matricesDirty_ = true;
|
||||
|
||||
/**
|
||||
* Calls to this.delayedRender_.start take advantage of requestAnimationFrame
|
||||
* (and friends) where available. The provided listener is called once in
|
||||
* the next available frame after the start method is called. A call to stop
|
||||
* will cancel the animation.
|
||||
*
|
||||
* @type {goog.async.AnimationDelay}
|
||||
* @private
|
||||
*/
|
||||
this.delayedRender_ = new goog.async.AnimationDelay(
|
||||
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>}
|
||||
@@ -102,6 +124,24 @@ ol.renderer.Map.prototype.addLayer = function(layer) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Must be called by subclasses after renderFrame completes.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.afterRenderFrame = function() {
|
||||
this.map.dispatchEvent(ol.MapEventType.POSTRENDER);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Must be called by subclasses before renderFrame executes.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.beforeRenderFrame = function() {
|
||||
this.pendingRender_ = false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Can rotate.
|
||||
*/
|
||||
@@ -309,12 +349,19 @@ ol.renderer.Map.prototype.removeLayerRenderer = function(layer) {
|
||||
* Render.
|
||||
*/
|
||||
ol.renderer.Map.prototype.render = function() {
|
||||
this.forEachReadyVisibleLayer(function(layer, layerRenderer) {
|
||||
layerRenderer.render();
|
||||
});
|
||||
if (!this.pendingRender_ && this.getMap().isDef()) {
|
||||
this.pendingRender_ = true;
|
||||
this.delayedRender_.start();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Render the map.
|
||||
*/
|
||||
ol.renderer.Map.prototype.renderFrame = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.layer.Layer} layer Layer.
|
||||
* @param {ol.renderer.Layer} layerRenderer Layer renderer.
|
||||
|
||||
@@ -548,11 +548,9 @@ ol.renderer.webgl.Map.prototype.removeLayerRenderer = function(layer) {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.render = function() {
|
||||
ol.renderer.webgl.Map.prototype.renderFrame = function() {
|
||||
|
||||
if (!this.getMap().isDef()) {
|
||||
return;
|
||||
}
|
||||
this.beforeRenderFrame();
|
||||
|
||||
var size = /** @type {ol.Size} */ this.getMap().getSize();
|
||||
if (!this.canvasSize_.equals(size)) {
|
||||
@@ -561,11 +559,8 @@ ol.renderer.webgl.Map.prototype.render = function() {
|
||||
this.canvasSize_ = size;
|
||||
}
|
||||
|
||||
var rerender = false;
|
||||
this.forEachReadyVisibleLayer(function(layer, layerRenderer) {
|
||||
if (layerRenderer.render()) {
|
||||
rerender = true;
|
||||
}
|
||||
layerRenderer.render();
|
||||
});
|
||||
|
||||
var gl = this.getGL();
|
||||
@@ -628,10 +623,7 @@ ol.renderer.webgl.Map.prototype.render = function() {
|
||||
gl.drawArrays(goog.webgl.TRIANGLE_STRIP, 0, 4);
|
||||
}, this);
|
||||
|
||||
if (rerender) {
|
||||
this.getMap().render();
|
||||
}
|
||||
|
||||
this.afterRenderFrame();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -526,6 +526,8 @@ ol.renderer.webgl.TileLayer.prototype.render = function() {
|
||||
-0.5,
|
||||
0);
|
||||
|
||||
return rerender;
|
||||
if (rerender) {
|
||||
mapRenderer.render();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user