diff --git a/src/ol/attribution.js b/src/ol/attribution.js index acf59930e3..4b4c8886e2 100644 --- a/src/ol/attribution.js +++ b/src/ol/attribution.js @@ -1,17 +1,13 @@ goog.provide('ol.Attribution'); -goog.require('ol.CoverageArea'); -goog.require('ol.Projection'); - /** * @constructor * @param {string} html HTML. - * @param {Array.=} opt_coverageAreas Coverage areas. - * @param {ol.Projection=} opt_projection Projection. + * @param {Object.>=} opt_tileRanges Tile ranges. */ -ol.Attribution = function(html, opt_coverageAreas, opt_projection) { +ol.Attribution = function(html, opt_tileRanges) { /** * @private @@ -21,38 +17,40 @@ ol.Attribution = function(html, opt_coverageAreas, opt_projection) { /** * @private - * @type {Array.} + * @type {Object.>} */ - this.coverageAreas_ = opt_coverageAreas || null; + this.tileRanges_ = opt_tileRanges || null; - /** - * @private - * @type {ol.Projection} - */ - this.projection_ = opt_projection || null; - -}; - - -/** - * @return {Array.} Coverage areas. - */ -ol.Attribution.prototype.getCoverageAreas = function() { - return this.coverageAreas_; }; /** * @return {string} HTML. */ -ol.Attribution.prototype.getHtml = function() { +ol.Attribution.prototype.getHTML = function() { return this.html_; }; /** - * @return {ol.Projection} Projection. + * @param {Object.} tileRanges Tile ranges. + * @return {boolean} Intersects any tile range. */ -ol.Attribution.prototype.getProjection = function() { - return this.projection_; +ol.Attribution.prototype.intersectsAnyTileRange = function(tileRanges) { + if (goog.isNull(this.tileRanges_)) { + return true; + } + var i, tileRange, z; + for (z in tileRanges) { + if (!(z in this.tileRanges_)) { + continue; + } + tileRange = tileRanges[z]; + for (i = 0; i < this.tileRanges_[z].length; ++i) { + if (this.tileRanges_[z][i].intersects(tileRange)) { + return true; + } + } + } + return false; }; diff --git a/src/ol/control/attributioncontrol.js b/src/ol/control/attributioncontrol.js index 27f5a7f836..f7148722e8 100644 --- a/src/ol/control/attributioncontrol.js +++ b/src/ol/control/attributioncontrol.js @@ -1,24 +1,15 @@ -// FIXME handle rotation // FIXME handle date line wrap -// FIXME handle layer order -// FIXME check clean-up code -// FIXME works for View2D only goog.provide('ol.control.Attribution'); +goog.require('goog.array'); goog.require('goog.dom'); goog.require('goog.dom.TagName'); goog.require('goog.events'); -goog.require('goog.events.EventType'); goog.require('goog.object'); goog.require('goog.style'); -goog.require('ol.Collection'); -goog.require('ol.CoverageArea'); -goog.require('ol.TileCoverageArea'); -goog.require('ol.View2D'); -goog.require('ol.View2DProperty'); +goog.require('ol.MapEventType'); goog.require('ol.control.Control'); -goog.require('ol.layer.Layer'); @@ -36,324 +27,50 @@ ol.control.Attribution = function(attributionOptions) { 'class': 'ol-attribution' }, this.ulElement_); - /** - * @private - * @type {Object.} - */ - this.layerVisibleChangeListenerKeys_ = {}; - - /** - * @private - * @type {Object.} - */ - this.attributionElements_ = {}; - - /** - * @private - * @type {Object.>} - */ - this.coverageAreass_ = {}; - - /** - * @private - * @type {Array.} - */ - this.mapListenerKeys_ = null; - - /** - * @private - * @type {Array.} - */ - this.layersListenerKeys_ = null; - - /** - * @private - * @type {Array.} - */ - this.viewListenerKeys_ = null; - goog.base(this, { element: element, map: attributionOptions.map, target: attributionOptions.target }); + /** + * @private + * @type {boolean} + */ + this.renderedVisible_ = true; + + /** + * @private + * @type {Object.} + */ + this.attributionElements_ = {}; + + /** + * @private + * @type {Object.} + */ + this.attributionElementRenderedVisible_ = {}; + + /** + * @private + * @type {Array.} + */ + this.listenerKeys_ = null; + }; goog.inherits(ol.control.Attribution, ol.control.Control); /** - * @param {ol.layer.Layer} layer Layer. - * @protected + * @param {ol.MapEvent} mapEvent Map event. */ -ol.control.Attribution.prototype.addLayer = function(layer) { - - var layerKey = goog.getUid(layer); - - this.layerVisibleChangeListenerKeys_[layerKey] = goog.events.listen( - layer, ol.Object.getChangedEventType(ol.layer.LayerProperty.VISIBLE), - this.handleLayerVisibleChanged, false, this); - - if (layer.getSource().isReady()) { - this.createAttributionElementsForLayer_(layer); +ol.control.Attribution.prototype.handleMapPostrender = function(mapEvent) { + var frameState = mapEvent.frameState; + if (goog.isNull(frameState)) { + this.updateElement_(null); } else { - goog.events.listenOnce(layer, goog.events.EventType.LOAD, - this.handleLayerLoad, false, this); + this.updateElement_(frameState.tileUsage); } - -}; - - -/** - * @param {ol.layer.Layer} layer Layer. - * @private - */ -ol.control.Attribution.prototype.createAttributionElementsForLayer_ = - function(layer) { - - var source = layer.getSource(); - var attributions = source.getAttributions(); - if (goog.isNull(attributions)) { - return; - } - - var map = this.getMap(); - var mapIsDef = map.isDef(); - var layerVisible = layer.getVisible(); - - var attributionVisibilities; - if (mapIsDef && layerVisible) { - var mapSize = /** @type {ol.Size} */ (map.getSize()); - // FIXME works for View2D only - var view = map.getView(); - goog.asserts.assert(view instanceof ol.View2D); - var mapExtent = view.getExtent(mapSize); - var mapProjection = /** @type {ol.Projection} */ (view.getProjection()); - var mapResolution = /** @type {number} */ (view.getResolution()); - attributionVisibilities = this.getLayerAttributionVisiblities_( - layer, mapExtent, mapResolution, mapProjection); - } else { - attributionVisibilities = null; - } - - goog.array.forEach(attributions, function(attribution) { - - var attributionKey = goog.getUid(attribution); - - var attributionElement = goog.dom.createElement(goog.dom.TagName.LI); - attributionElement.innerHTML = attribution.getHtml(); - - if (!mapIsDef || - !layerVisible || - goog.isNull(attributionVisibilities) || - !attributionVisibilities[attributionKey]) { - if (goog.style.isElementShown(attributionElement)) { - goog.style.showElement(attributionElement, false); - } - } - - goog.dom.appendChild(this.ulElement_, attributionElement); - - this.attributionElements_[attributionKey] = attributionElement; - - }, this); - -}; - - -/** - * @param {ol.layer.Layer} layer Layer. - * @param {ol.Extent} mapExtent View extent. - * @param {number} mapResolution View resolution. - * @param {ol.Projection} mapProjection Map projection. - * @return {Object.} Attribution visibilities. - * @private - */ -ol.control.Attribution.prototype.getLayerAttributionVisiblities_ = - function(layer, mapExtent, mapResolution, mapProjection) { - - var source = layer.getSource(); - var attributions = source.getAttributions(); - - if (goog.isNull(attributions)) { - return null; - } - - var mapZ; - if (source instanceof ol.source.TileSource) { - var tileSource = /** @type {ol.source.TileSource} */ (source); - var tileGrid = tileSource.getTileGrid(); - mapZ = tileGrid.getZForResolution(mapResolution); - } - - var attributionVisibilities = {}; - goog.array.forEach(attributions, function(attribution) { - - var attributionKey = goog.getUid(attribution); - - var attributionVisible = true; - - var coverageAreas; - if (attributionKey in this.coverageAreass_) { - coverageAreas = this.coverageAreass_[attributionKey]; - } else { - var attributionProjection = attribution.getProjection(); - coverageAreas = attribution.getCoverageAreas(); - if (!goog.isNull(coverageAreas) && - !ol.Projection.equivalent(attributionProjection, mapProjection)) { - var transformFn = ol.Projection.getTransform( - attributionProjection, mapProjection); - if (transformFn !== ol.Projection.cloneTransform) { - coverageAreas = goog.array.map(coverageAreas, function(coverageArea) { - return coverageArea.transform(transformFn); - }); - } - } - this.coverageAreass_[attributionKey] = coverageAreas; - } - - if (!goog.isNull(coverageAreas)) { - if (source instanceof ol.source.TileSource) { - attributionVisible = goog.array.some( - coverageAreas, - function(coverageArea, index) { - return coverageArea.intersectsExtentAndZ(mapExtent, mapZ); - }); - } else { - attributionVisible = goog.array.some( - coverageAreas, - function(coverageArea) { - return coverageArea.intersectsExtentAndResolution( - mapExtent, mapResolution); - }); - } - } - - attributionVisibilities[attributionKey] = attributionVisible; - - }, this); - - return attributionVisibilities; - -}; - - -/** - * @param {goog.events.Event} event Event. - */ -ol.control.Attribution.prototype.handleLayerLoad = function(event) { - var layer = /** @type {ol.layer.Layer} */ (event.target); - this.createAttributionElementsForLayer_(layer); -}; - - -/** - * @param {goog.events.Event} event Event. - * @protected - */ -ol.control.Attribution.prototype.handleLayerVisibleChanged = function(event) { - var layer = /** @type {ol.layer.Layer} */ (event.target); - this.updateLayerAttributionsVisibility_(layer); - -}; - - -/** - * @param {ol.CollectionEvent} collectionEvent Collection event. - * @protected - */ -ol.control.Attribution.prototype.handleLayersAdd = function(collectionEvent) { - var layer = /** @type {ol.layer.Layer} */ (collectionEvent.elem); - this.addLayer(layer); -}; - - -/** - * @param {ol.CollectionEvent} collectionEvent Collection event. - * @protected - */ -ol.control.Attribution.prototype.handleLayersRemove = - function(collectionEvent) { - var layer = /** @type {ol.layer.Layer} */ (collectionEvent.elem); - this.removeLayer(layer); -}; - - -/** - * @protected - */ -ol.control.Attribution.prototype.handleMapViewChanged = function() { - if (!goog.isNull(this.viewListenerKeys_)) { - goog.array.forEach(this.viewListenerKeys_, goog.events.unlistenByKey); - this.viewListenerKeys_ = null; - } - var map = this.getMap(); - goog.asserts.assert(!goog.isNull(map)); - var view = map.getView(); - if (!goog.isNull(view)) { - // FIXME works for View2D only - goog.asserts.assert(view instanceof ol.View2D); - this.viewListenerKeys_ = [ - goog.events.listen( - view, ol.Object.getChangedEventType(ol.View2DProperty.CENTER), - this.updateAttributions, false, this), - goog.events.listen( - view, ol.Object.getChangedEventType(ol.View2DProperty.RESOLUTION), - this.updateAttributions, false, this) - ]; - } -}; - - -/** - * @protected - */ -ol.control.Attribution.prototype.handleMapLayersChanged = function() { - if (!goog.isNull(this.layersListenerKeys_)) { - goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey); - this.layersListenerKeys_ = null; - } - goog.object.forEach(this.attributionElements_, function(attributionElement) { - goog.dom.removeNode(attributionElement); - }, this); - this.attributionElements_ = {}; - this.coverageAreass_ = {}; - var map = this.getMap(); - var layers = map.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.layer.Layer} layer Layer. - * @protected - */ -ol.control.Attribution.prototype.removeLayer = function(layer) { - - var layerKey = goog.getUid(layer); - - goog.events.unlistenByKey(this.layerVisibleChangeListenerKeys_[layerKey]); - delete this.layerVisibleChangeListenerKeys_[layerKey]; - - goog.array.forEach( - layer.getSource().getAttributions(), - function(attribution) { - var attributionKey = goog.getUid(attribution); - delete this.coverageAreass_[attributionKey]; - var attributionElement = this.attributionElements_[attributionKey]; - goog.dom.removeNode(attributionElement); - delete this.attributionElements_[attributionKey]; - }, - this); - }; @@ -361,79 +78,116 @@ ol.control.Attribution.prototype.removeLayer = function(layer) { * @inheritDoc */ ol.control.Attribution.prototype.setMap = function(map) { - if (!goog.isNull(this.mapListenerKeys_)) { - goog.array.forEach(this.mapListenerKeys_, goog.events.unlistenByKey); + if (!goog.isNull(this.listenerKeys_)) { + goog.array.forEach(this.listenerKeys_, goog.events.unlistenByKey); + this.listenerKeys_ = null; } - this.mapListenerKeys_ = null; goog.base(this, 'setMap', map); if (!goog.isNull(map)) { - this.mapListenerKeys_ = [ - goog.events.listen( - map, ol.Object.getChangedEventType(ol.MapProperty.LAYERS), - this.handleMapLayersChanged, false, this), - goog.events.listen( - map, ol.Object.getChangedEventType(ol.MapProperty.SIZE), - this.updateAttributions, false, this), - goog.events.listen( - map, ol.Object.getChangedEventType(ol.MapProperty.VIEW), - this.updateAttributions, false, this) + this.listenerKeys_ = [ + goog.events.listen(map, ol.MapEventType.POSTRENDER, + this.handleMapPostrender, false, this) ]; - this.handleMapViewChanged(); - this.handleMapLayersChanged(); } }; /** - * @protected - */ -ol.control.Attribution.prototype.updateAttributions = function() { - - var map = this.getMap(); - var layers = map.getLayers(); - layers.forEach(function(layer) { - this.updateLayerAttributionsVisibility_(layer); - }, this); - -}; - - -/** - * @param {ol.layer.Layer} layer Layer. * @private + * @param {?Object.>} tileUsage Tile + * usage. */ -ol.control.Attribution.prototype.updateLayerAttributionsVisibility_ = - function(layer) { +ol.control.Attribution.prototype.updateElement_ = function(tileUsage) { + + if (goog.isNull(tileUsage)) { + if (this.renderedVisible_) { + goog.style.showElement(this.element, false); + this.renderedVisible_ = false; + } + return; + } + var map = this.getMap(); - if (map.isDef() && layer.getVisible()) { - var mapSize = /** @type {ol.Size} */ (map.getSize()); - var view = map.getView(); - // FIXME works for View2D only - goog.asserts.assert(view instanceof ol.View2D); - var mapExtent = view.getExtent(mapSize); - var mapProjection = /** @type {ol.Projection} */ (view.getProjection()); - var mapResolution = /** @type {number} */ (view.getResolution()); - var attributionVisibilities = this.getLayerAttributionVisiblities_( - layer, mapExtent, mapResolution, mapProjection); - goog.object.forEach( - attributionVisibilities, - function(attributionVisible, attributionKey) { - var attributionElement = this.attributionElements_[attributionKey]; - if (goog.style.isElementShown(attributionElement) != - attributionVisible) { - goog.style.showElement(attributionElement, attributionVisible); - } - }, - this); - } else { - var source = layer.getSource(); - var attributions = source.getAttributions(); - if (!goog.isNull(attributions)) { - goog.array.forEach(attributions, function(attribution) { - var attributionKey = goog.getUid(attribution); - var attributionElement = this.attributionElements_[attributionKey]; - goog.style.showElement(attributionElement, false); - }, this); + + /** @type {Object.} */ + var attributionsToRemove = {}; + /** @type {Object.} */ + var tileSources = {}; + var layers = map.getLayers(); + if (goog.isDef(layers)) { + layers.forEach(function(layer) { + var source = layer.getSource(); + if (source instanceof ol.source.TileSource) { + tileSources[goog.getUid(source).toString()] = source; + } + var attributions = source.getAttributions(); + if (!goog.isNull(attributions)) { + var attribution, i; + for (i = 0; i < attributions.length; ++i) { + attribution = attributions[i]; + attributionKey = goog.getUid(attribution).toString(); + attributionsToRemove[attributionKey] = true; + } + } + }); + } + + /** @type {Object.} */ + var attributions = {}; + var i, tileRanges, tileSource, tileSourceAttribution, + tileSourceAttributionKey, tileSourceAttributions, tileSourceKey, z; + for (tileSourceKey in tileUsage) { + goog.asserts.assert(tileSourceKey in tileSources); + tileSource = tileSources[tileSourceKey]; + tileSourceAttributions = tileSource.getAttributions(); + if (goog.isNull(tileSourceAttributions)) { + continue; + } + tileRanges = tileUsage[tileSourceKey]; + for (i = 0; i < tileSourceAttributions.length; ++i) { + tileSourceAttribution = tileSourceAttributions[i]; + tileSourceAttributionKey = goog.getUid(tileSourceAttribution).toString(); + if (tileSourceAttributionKey in attributions) { + continue; + } + if (tileSourceAttribution.intersectsAnyTileRange(tileRanges)) { + attributions[tileSourceAttributionKey] = tileSourceAttribution; + } } } + + /** @type {Array.} */ + var attributionKeys = + goog.array.map(goog.object.getKeys(attributions), Number); + goog.array.sort(attributionKeys); + var attributionElement, attributionKey; + for (i = 0; i < attributionKeys.length; ++i) { + attributionKey = attributionKeys[i].toString(); + if (attributionKey in this.attributionElements_) { + if (!this.attributionElementRenderedVisible_[attributionKey]) { + goog.style.showElement(this.attributionElements_[attributionKey], true); + this.attributionElementRenderedVisible_[attributionKey] = true; + } + } else { + attributionElement = goog.dom.createElement(goog.dom.TagName.LI); + attributionElement.innerHTML = attributions[attributionKey].getHTML(); + goog.dom.appendChild(this.ulElement_, attributionElement); + this.attributionElements_[attributionKey] = attributionElement; + this.attributionElementRenderedVisible_[attributionKey] = true; + } + delete attributionsToRemove[attributionKey]; + } + + for (attributionKey in attributionsToRemove) { + goog.dom.removeNode(this.attributionElements_[attributionKey]); + delete this.attributionElements_[attributionKey]; + delete this.attributionElementRenderedVisible_[attributionKey]; + } + + var renderVisible = !goog.array.isEmpty(attributionKeys); + if (this.renderedVisible_ != renderVisible) { + goog.style.showElement(this.element, renderVisible); + this.renderedVisible_ = renderVisible; + } + }; diff --git a/src/ol/coveragearea.js b/src/ol/coveragearea.js deleted file mode 100644 index 55fe982796..0000000000 --- a/src/ol/coveragearea.js +++ /dev/null @@ -1,55 +0,0 @@ -goog.provide('ol.CoverageArea'); - -goog.require('ol.Extent'); - - - -/** - * Represents a rectangular area. - * - * @constructor - * @param {ol.Extent} extent Extent. - */ -ol.CoverageArea = function(extent) { - - /** - * @type {ol.Extent} - */ - this.extent = extent; - -}; - - -/** - * @param {ol.Extent} extent Extent. - * @return {boolean} Intersects. - */ -ol.CoverageArea.prototype.intersectsExtent = function(extent) { - return this.extent.intersects(extent); -}; - - -/** - * @param {ol.Extent} extent Extent. - * @param {number} resolution Resolution. - * @return {boolean} Intersects. - */ -ol.CoverageArea.prototype.intersectsExtentAndResolution = goog.abstractMethod; - - -/** - * @param {ol.Extent} extent Extent. - * @param {number} z Z. - * @return {boolean} Intersects. - */ -ol.CoverageArea.prototype.intersectsExtentAndZ = goog.abstractMethod; - - -/** - * @param {ol.TransformFunction} transformFn Transform. - * @return {ol.CoverageArea} Transformed coverage area. - */ -ol.CoverageArea.prototype.transform = function(transformFn) { - var extent = this.extent.transform(transformFn); - return new ol.CoverageArea(extent); -}; diff --git a/src/ol/framestate.js b/src/ol/framestate.js index d84f4de831..574fefe20f 100644 --- a/src/ol/framestate.js +++ b/src/ol/framestate.js @@ -10,6 +10,7 @@ goog.require('ol.Coordinate'); goog.require('ol.Extent'); goog.require('ol.Size'); goog.require('ol.TileQueue'); +goog.require('ol.TileRange'); goog.require('ol.View2DState'); goog.require('ol.layer.LayerState'); @@ -25,6 +26,7 @@ goog.require('ol.layer.LayerState'); * postRenderFunctions: Array., * size: ol.Size, * tileQueue: ol.TileQueue, + * tileUsage: Object.>, * time: number, * view2DState: ol.View2DState, * viewHints: Array.}} diff --git a/src/ol/map.js b/src/ol/map.js index f82253eeaf..383529adeb 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -617,6 +617,7 @@ ol.Map.prototype.renderFrame_ = function(time) { postRenderFunctions: [], size: size, tileQueue: this.tileQueue_, + tileUsage: {}, view2DState: view2DState, viewHints: viewHints, time: time diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index cdbfb92305..f80ca05e04 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -89,6 +89,21 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = var tileRange = tileGrid.getTileRangeForExtentAndResolution( frameState.extent, tileResolution); + // FIXME should also consider interim tiles + var tileUsage = frameState.tileUsage; + var tileSourceKey = goog.getUid(tileSource).toString(); + var zKey = z.toString(); + if (tileSourceKey in tileUsage) { + if (z in tileUsage[tileSourceKey]) { + tileUsage[tileSourceKey][zKey].extend(tileRange); + } else { + tileUsage[tileSourceKey][zKey] = tileRange; + } + } else { + tileUsage[tileSourceKey] = {}; + tileUsage[tileSourceKey][zKey] = tileRange; + } + /** @type {Object.>} */ var tilesToDrawByZ = {}; tilesToDrawByZ[z] = {}; diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index 43f83838fd..e9ddb277b3 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -276,6 +276,21 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = var tileRange = tileGrid.getTileRangeForExtentAndResolution( frameState.extent, tileResolution); + // FIXME should also consider interim tiles + var tileUsage = frameState.tileUsage; + var tileSourceKey = goog.getUid(tileSource).toString(); + var zKey = z.toString(); + if (tileSourceKey in tileUsage) { + if (z in tileUsage[tileSourceKey]) { + tileUsage[tileSourceKey][zKey].extend(tileRange); + } else { + tileUsage[tileSourceKey][zKey] = tileRange; + } + } else { + tileUsage[tileSourceKey] = {}; + tileUsage[tileSourceKey][zKey] = tileRange; + } + var framebufferExtent; if (!goog.isNull(this.renderedTileRange_) && diff --git a/src/ol/source/bingmapssource.js b/src/ol/source/bingmapssource.js index 7693cb81d9..a700ba09d2 100644 --- a/src/ol/source/bingmapssource.js +++ b/src/ol/source/bingmapssource.js @@ -5,7 +5,7 @@ goog.require('goog.Uri'); goog.require('goog.events'); goog.require('goog.events.EventType'); goog.require('goog.net.Jsonp'); -goog.require('ol.TileCoverageArea'); +goog.require('ol.TileRange'); goog.require('ol.source.ImageTileSource'); goog.require('ol.tilegrid.XYZ'); @@ -118,21 +118,35 @@ ol.source.BingMaps.prototype.handleImageryMetadataResponse = }; }))); - var projection = ol.Projection.getFromCode('EPSG:4326'); + var transform = ol.Projection.getTransform( + ol.Projection.getFromCode('EPSG:4326'), this.getProjection()); var attributions = goog.array.map( resource.imageryProviders, function(imageryProvider) { var html = imageryProvider.attribution; - var coverageAreas = goog.array.map( + /** @type {Object.>} */ + var tileRanges = {}; + goog.array.forEach( imageryProvider.coverageAreas, function(coverageArea) { - var bbox = coverageArea.bbox; - var extent = new ol.Extent(bbox[1], bbox[0], bbox[3], bbox[2]); var minZ = coverageArea.zoomMin; var maxZ = coverageArea.zoomMax; - return new ol.TileCoverageArea(tileGrid, extent, minZ, maxZ); + var bbox = coverageArea.bbox; + var epsg4326Extent = + new ol.Extent(bbox[1], bbox[0], bbox[3], bbox[2]); + var extent = epsg4326Extent.transform(transform); + var tileRange, z, zKey; + for (z = minZ; z <= maxZ; ++z) { + zKey = z.toString(); + tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z); + if (zKey in tileRanges) { + tileRanges[zKey].push(tileRange); + } else { + tileRanges[zKey] = [tileRange]; + } + } }); - return new ol.Attribution(html, coverageAreas, projection); + return new ol.Attribution(html, tileRanges); }); this.setAttributions(attributions); diff --git a/src/ol/source/tilejsonsource.js b/src/ol/source/tilejsonsource.js index 81eacaf7a4..af306b0d26 100644 --- a/src/ol/source/tilejsonsource.js +++ b/src/ol/source/tilejsonsource.js @@ -14,7 +14,6 @@ goog.require('goog.events.EventType'); goog.require('goog.net.jsloader'); goog.require('goog.string'); goog.require('ol.Projection'); -goog.require('ol.TileCoverageArea'); goog.require('ol.TileUrlFunction'); goog.require('ol.source.ImageTileSource'); goog.require('ol.tilegrid.XYZ'); @@ -98,17 +97,17 @@ ol.source.TileJSON.prototype.handleTileJSONResponse = function() { if (goog.isDef(tileJSON.scheme)) { goog.asserts.assert(tileJSON.scheme == 'xyz'); } - var minzoom = tileJSON.minzoom || 0; - goog.asserts.assert(minzoom === 0); // FIXME - var maxzoom = tileJSON.maxzoom || 22; + var minZoom = tileJSON.minzoom || 0; + goog.asserts.assert(minZoom === 0); // FIXME + var maxZoom = tileJSON.maxzoom || 22; var tileGrid = new ol.tilegrid.XYZ({ - maxZoom: maxzoom + maxZoom: maxZoom }); this.tileGrid = tileGrid; this.tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform( function(tileCoord) { - if (tileCoord.z < minzoom || maxzoom < tileCoord.z) { + if (tileCoord.z < minZoom || maxZoom < tileCoord.z) { return null; } var n = 1 << tileCoord.z; @@ -129,13 +128,18 @@ ol.source.TileJSON.prototype.handleTileJSONResponse = function() { ol.TileUrlFunction.createFromTemplates(tileJSON.tiles)); if (goog.isDef(tileJSON.attribution)) { - var coverageAreas = [ - new ol.TileCoverageArea(tileGrid, epsg4326Extent, minzoom, maxzoom) - ]; - var coverageAreaProjection = epsg4326Projection; + var attributionExtent = goog.isNull(extent) ? + epsg4326Projection.getExtent() : extent; + /** @type {Object.>} */ + var tileRanges = {}; + var z, zKey; + for (z = minZoom; z <= maxZoom; ++z) { + zKey = z.toString(); + tileRanges[zKey] = + [tileGrid.getTileRangeForExtentAndZ(attributionExtent, z)]; + } this.setAttributions([ - new ol.Attribution( - tileJSON.attribution, coverageAreas, coverageAreaProjection) + new ol.Attribution(tileJSON.attribution, tileRanges) ]); } diff --git a/src/ol/tilecoveragearea.js b/src/ol/tilecoveragearea.js deleted file mode 100644 index f09e1d1797..0000000000 --- a/src/ol/tilecoveragearea.js +++ /dev/null @@ -1,69 +0,0 @@ -goog.provide('ol.TileCoverageArea'); - -goog.require('ol.CoverageArea'); -goog.require('ol.Extent'); -goog.require('ol.tilegrid.TileGrid'); - - - -/** - * @constructor - * @extends {ol.CoverageArea} - * @param {ol.tilegrid.TileGrid} tileGrid Tile grid. - * @param {ol.Extent} extent Extent. - * @param {number} minZ Minimum Z. - * @param {number} maxZ Maximum Z. - */ -ol.TileCoverageArea = function(tileGrid, extent, minZ, maxZ) { - - goog.base(this, extent); - - /** - * @private - * @type {ol.tilegrid.TileGrid} - */ - this.tileGrid_ = tileGrid; - - /** - * @private - * @type {number} - */ - this.minZ_ = minZ; - - /** - * @private - * @type {number} - */ - this.maxZ_ = maxZ; - -}; -goog.inherits(ol.TileCoverageArea, ol.CoverageArea); - - -/** - * @inheritDoc - */ -ol.TileCoverageArea.prototype.intersectsExtentAndResolution = - function(extent, resolution) { - var z = this.tileGrid_.getZForResolution(resolution); - return this.intersectsExtentAndZ(extent, z); -}; - - -/** - * @inheritDoc - */ -ol.TileCoverageArea.prototype.intersectsExtentAndZ = function(extent, z) { - return this.minZ_ <= z && z <= this.maxZ_ && this.intersectsExtent(extent); -}; - - -/** - * @param {ol.TransformFunction} transformFn Transform. - * @return {ol.TileCoverageArea} Transformed tile coverage area. - */ -ol.TileCoverageArea.prototype.transform = function(transformFn) { - var extent = this.extent.transform(transformFn); - return new ol.TileCoverageArea( - this.tileGrid_, extent, this.minZ_, this.maxZ_); -};