diff --git a/src/ol/map.js b/src/ol/map.js index 7945fd464a..70cb4928a4 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -29,6 +29,8 @@ goog.require('goog.style'); goog.require('goog.vec.Mat4'); goog.require('ol.BrowserFeature'); goog.require('ol.Collection'); +goog.require('ol.CollectionEvent'); +goog.require('ol.CollectionEventType'); goog.require('ol.Color'); goog.require('ol.Extent'); goog.require('ol.FrameState'); @@ -298,6 +300,14 @@ ol.Map = function(options) { goog.bind(this.getTilePriority, this), goog.bind(this.handleTileChange_, this)); + /** + * @private + * @type {Array.} + */ + this.layersListenerKeys_ = null; + + goog.events.listen(this, ol.Object.getChangedEventType(ol.MapProperty.LAYERS), + this.handleLayersChanged_, false, this); goog.events.listen(this, ol.Object.getChangedEventType(ol.MapProperty.VIEW), this.handleViewChanged_, false, this); goog.events.listen(this, ol.Object.getChangedEventType(ol.MapProperty.SIZE), @@ -305,6 +315,7 @@ ol.Map = function(options) { goog.events.listen( this, ol.Object.getChangedEventType(ol.MapProperty.BACKGROUND_COLOR), this.handleBackgroundColorChanged_, false, this); + this.setValues(optionsInternal.values); // this gives the map an initial size @@ -552,6 +563,46 @@ ol.Map.prototype.handleBrowserEvent = function(browserEvent, opt_type) { }; +/** + * @param {ol.CollectionEvent} collectionEvent Collection event. + * @private + */ +ol.Map.prototype.handleLayersAdd_ = function(collectionEvent) { + this.render(); +}; + + +/** + * @param {goog.events.Event} event Event. + * @private + */ +ol.Map.prototype.handleLayersChanged_ = function(event) { + if (!goog.isNull(this.layersListenerKeys_)) { + goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey); + this.layersListenerKeys_ = null; + } + var layers = this.getLayers(); + if (goog.isDefAndNotNull(layers)) { + this.layersListenerKeys_ = [ + goog.events.listen(layers, ol.CollectionEventType.ADD, + this.handleLayersAdd_, false, this), + goog.events.listen(layers, ol.CollectionEventType.REMOVE, + this.handleLayersRemove_, false, this) + ]; + } + this.render(); +}; + + +/** + * @param {ol.CollectionEvent} collectionEvent Collection event. + * @private + */ +ol.Map.prototype.handleLayersRemove_ = function(collectionEvent) { + this.render(); +}; + + /** * @param {ol.MapBrowserEvent} mapBrowserEvent The event to handle. */ diff --git a/src/ol/renderer/canvas/canvasmaprenderer.js b/src/ol/renderer/canvas/canvasmaprenderer.js index 69191c5bae..0de485157b 100644 --- a/src/ol/renderer/canvas/canvasmaprenderer.js +++ b/src/ol/renderer/canvas/canvasmaprenderer.js @@ -153,4 +153,6 @@ ol.renderer.canvas.Map.prototype.renderFrame = function(frameState) { this.renderedVisible_ = true; } + this.scheduleRemoveUnusedLayerRenderers(frameState); + }; diff --git a/src/ol/renderer/dom/dommaprenderer.js b/src/ol/renderer/dom/dommaprenderer.js index f821be3f07..14072ba424 100644 --- a/src/ol/renderer/dom/dommaprenderer.js +++ b/src/ol/renderer/dom/dommaprenderer.js @@ -93,5 +93,6 @@ ol.renderer.dom.Map.prototype.renderFrame = function(frameState) { } this.calculateMatrices2D(frameState); + this.scheduleRemoveUnusedLayerRenderers(frameState); }; diff --git a/src/ol/renderer/maprenderer.js b/src/ol/renderer/maprenderer.js index 870cb37fdb..adc4de270f 100644 --- a/src/ol/renderer/maprenderer.js +++ b/src/ol/renderer/maprenderer.js @@ -1,7 +1,6 @@ goog.provide('ol.renderer.Map'); goog.require('goog.Disposable'); -goog.require('goog.array'); goog.require('goog.asserts'); goog.require('goog.dispose'); goog.require('goog.events'); @@ -9,10 +8,7 @@ goog.require('goog.events.EventType'); goog.require('goog.functions'); goog.require('goog.object'); goog.require('goog.vec.Mat4'); -goog.require('ol.CollectionEvent'); -goog.require('ol.CollectionEventType'); goog.require('ol.FrameState'); -goog.require('ol.Object'); goog.require('ol.layer.Layer'); goog.require('ol.renderer.Layer'); @@ -42,32 +38,13 @@ ol.renderer.Map = function(container, map) { /** * @private - * @type {Object.} + * @type {Object.} */ this.layerRenderers_ = {}; - // - // We listen to layer add/remove to add/remove layer renderers. - // - /** * @private - * @type {?number} - */ - this.mapLayersChangedListenerKey_ = - goog.events.listen( - map, ol.Object.getChangedEventType(ol.MapProperty.LAYERS), - this.handleLayersChanged_, false, this); - - /** - * @private - * @type {Array.} - */ - this.layersListenerKeys_ = null; - - /** - * @private - * @type {Object.} + * @type {Object.} */ this.layerRendererChangeListenKeys_ = {}; @@ -75,17 +52,6 @@ ol.renderer.Map = function(container, map) { goog.inherits(ol.renderer.Map, goog.Disposable); -/** - * @param {ol.layer.Layer} layer Layer. - * @private - */ -ol.renderer.Map.prototype.addLayer_ = function(layer) { - var layerRenderer = this.createLayerRenderer(layer); - this.setLayerRenderer_(layer, layerRenderer); - this.getMap().render(); -}; - - /** * @param {ol.FrameState} frameState FrameState. * @protected @@ -135,10 +101,8 @@ ol.renderer.Map.prototype.disposeInternal = function() { goog.object.forEach(this.layerRenderers_, function(layerRenderer) { goog.dispose(layerRenderer); }); - goog.events.unlistenByKey(this.mapLayersChangedListenerKey_); - if (!goog.isNull(this.layersListenerKeys_)) { - goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey); - } + goog.object.forEach( + this.layerRendererChangeListenKeys_, goog.events.unlistenByKey); goog.base(this, 'disposeInternal'); }; @@ -155,10 +119,17 @@ ol.renderer.Map.prototype.getCanvas = goog.functions.NULL; * @return {ol.renderer.Layer} Layer renderer. */ ol.renderer.Map.prototype.getLayerRenderer = function(layer) { - var layerKey = goog.getUid(layer); - var layerRenderer = this.layerRenderers_[layerKey]; - goog.asserts.assert(goog.isDef(layerRenderer)); - return layerRenderer; + var layerKey = goog.getUid(layer).toString(); + if (layerKey in this.layerRenderers_) { + return this.layerRenderers_[layerKey]; + } else { + var layerRenderer = this.createLayerRenderer(layer); + this.layerRenderers_[layerKey] = layerRenderer; + this.layerRendererChangeListenKeys_[layerKey] = goog.events.listen( + layerRenderer, goog.events.EventType.CHANGE, + this.handleLayerRendererChange_, false, this); + return layerRenderer; + } }; @@ -189,74 +160,18 @@ ol.renderer.Map.prototype.handleLayerRendererChange_ = function(event) { /** - * @param {ol.CollectionEvent} collectionEvent Collection event. - * @private - */ -ol.renderer.Map.prototype.handleLayersAdd_ = function(collectionEvent) { - var layer = /** @type {ol.layer.Layer} */ (collectionEvent.elem); - this.addLayer_(layer); -}; - - -/** - * @private - */ -ol.renderer.Map.prototype.handleLayersChanged_ = function() { - goog.disposeAll(goog.object.getValues(this.layerRenderers_)); - this.layerRenderers_ = {}; - if (!goog.isNull(this.layersListenerKeys_)) { - goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey); - this.layersListenerKeys_ = null; - } - var layers = this.getMap().getLayers(); - if (goog.isDefAndNotNull(layers)) { - layers.forEach(this.addLayer_, this); - this.layersListenerKeys_ = [ - goog.events.listen(layers, ol.CollectionEventType.ADD, - this.handleLayersAdd_, false, this), - goog.events.listen(layers, ol.CollectionEventType.REMOVE, - this.handleLayersRemove_, false, this) - ]; - } -}; - - -/** - * @param {ol.CollectionEvent} collectionEvent Collection event. - * @private - */ -ol.renderer.Map.prototype.handleLayersRemove_ = function(collectionEvent) { - var layer = /** @type {ol.layer.Layer} */ (collectionEvent.elem); - this.removeLayer_(layer); -}; - - -/** - * @param {ol.layer.Layer} layer Layer. - * @private - */ -ol.renderer.Map.prototype.removeLayer_ = function(layer) { - goog.dispose(this.removeLayerRenderer_(layer)); - this.getMap().render(); -}; - - -/** - * @param {ol.layer.Layer} layer Layer. + * @param {string} layerKey Layer key. * @return {ol.renderer.Layer} Layer renderer. * @private */ -ol.renderer.Map.prototype.removeLayerRenderer_ = function(layer) { - var layerKey = goog.getUid(layer); - if (layerKey in this.layerRenderers_) { - var layerRenderer = this.layerRenderers_[layerKey]; - delete this.layerRenderers_[layerKey]; - goog.events.unlistenByKey(this.layerRendererChangeListenKeys_[layerKey]); - delete this.layerRendererChangeListenKeys_[layerKey]; - return layerRenderer; - } else { - return null; - } +ol.renderer.Map.prototype.removeLayerRendererByKey_ = function(layerKey) { + goog.asserts.assert(layerKey in this.layerRenderers_); + var layerRenderer = this.layerRenderers_[layerKey]; + delete this.layerRenderers_[layerKey]; + goog.asserts.assert(layerKey in this.layerRendererChangeListenKeys_); + goog.events.unlistenByKey(this.layerRendererChangeListenKeys_[layerKey]); + delete this.layerRendererChangeListenKeys_[layerKey]; + return layerRenderer; }; @@ -268,16 +183,33 @@ ol.renderer.Map.prototype.renderFrame = goog.nullFunction; /** - * @param {ol.layer.Layer} layer Layer. - * @param {ol.renderer.Layer} layerRenderer Layer renderer. + * @param {ol.Map} map Map. + * @param {ol.FrameState} frameState Frame state. * @private */ -ol.renderer.Map.prototype.setLayerRenderer_ = function(layer, layerRenderer) { - var layerKey = goog.getUid(layer); - goog.asserts.assert(!(layerKey in this.layerRenderers_)); - this.layerRenderers_[layerKey] = layerRenderer; - goog.asserts.assert(!(layerKey in this.layerRendererChangeListenKeys_)); - this.layerRendererChangeListenKeys_[layerKey] = goog.events.listen( - layerRenderer, goog.events.EventType.CHANGE, - this.handleLayerRendererChange_, false, this); +ol.renderer.Map.prototype.removeUnusedLayerRenderers_ = + function(map, frameState) { + var layerKey; + for (layerKey in this.layerRenderers_) { + if (goog.isNull(frameState) || !(layerKey in frameState.layerStates)) { + goog.dispose(this.removeLayerRendererByKey_(layerKey)); + } + } +}; + + +/** + * @param {!ol.FrameState} frameState Frame state. + * @protected + */ +ol.renderer.Map.prototype.scheduleRemoveUnusedLayerRenderers = + function(frameState) { + var layerKey; + for (layerKey in this.layerRenderers_) { + if (!(layerKey in frameState.layerStates)) { + frameState.postRenderFunctions.push( + goog.bind(this.removeUnusedLayerRenderers_, this)); + return; + } + } }; diff --git a/src/ol/renderer/webgl/webglmaprenderer.js b/src/ol/renderer/webgl/webglmaprenderer.js index 77b03c3d36..465a2ab8d2 100644 --- a/src/ol/renderer/webgl/webglmaprenderer.js +++ b/src/ol/renderer/webgl/webglmaprenderer.js @@ -641,4 +641,6 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) { frameState.animate = true; } + this.scheduleRemoveUnusedLayerRenderers(frameState); + };