Refactor attribution control

This commit is contained in:
Tom Payne
2013-01-16 16:34:31 +01:00
parent 41ccb4dfcd
commit 9fbabc3696
10 changed files with 224 additions and 545 deletions

View File

@@ -1,17 +1,13 @@
goog.provide('ol.Attribution');
goog.require('ol.CoverageArea');
goog.require('ol.Projection');
/**
* @constructor
* @param {string} html HTML.
* @param {Array.<ol.CoverageArea>=} opt_coverageAreas Coverage areas.
* @param {ol.Projection=} opt_projection Projection.
* @param {Object.<string, Array.<ol.TileRange>>=} 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.<ol.CoverageArea>}
* @type {Object.<string, Array.<ol.TileRange>>}
*/
this.coverageAreas_ = opt_coverageAreas || null;
this.tileRanges_ = opt_tileRanges || null;
/**
* @private
* @type {ol.Projection}
*/
this.projection_ = opt_projection || null;
};
/**
* @return {Array.<ol.CoverageArea>} 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.<string, ol.TileRange>} 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;
};

View File

@@ -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.<number, ?number>}
*/
this.layerVisibleChangeListenerKeys_ = {};
/**
* @private
* @type {Object.<number, Element>}
*/
this.attributionElements_ = {};
/**
* @private
* @type {Object.<number, Array.<ol.CoverageArea>>}
*/
this.coverageAreass_ = {};
/**
* @private
* @type {Array.<number>}
*/
this.mapListenerKeys_ = null;
/**
* @private
* @type {Array.<number>}
*/
this.layersListenerKeys_ = null;
/**
* @private
* @type {Array.<number>}
*/
this.viewListenerKeys_ = null;
goog.base(this, {
element: element,
map: attributionOptions.map,
target: attributionOptions.target
});
/**
* @private
* @type {boolean}
*/
this.renderedVisible_ = true;
/**
* @private
* @type {Object.<string, Element>}
*/
this.attributionElements_ = {};
/**
* @private
* @type {Object.<string, boolean>}
*/
this.attributionElementRenderedVisible_ = {};
/**
* @private
* @type {Array.<?number>}
*/
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.<number, boolean>} 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.<string, Object.<string, ol.TileRange>>} 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.<string, boolean>} */
var attributionsToRemove = {};
/** @type {Object.<string, ol.source.TileSource>} */
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.<string, ol.Attribution>} */
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.<number>} */
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;
}
};

View File

@@ -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);
};

View File

@@ -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.<ol.PostRenderFunction>,
* size: ol.Size,
* tileQueue: ol.TileQueue,
* tileUsage: Object.<string, Object.<string, ol.TileRange>>,
* time: number,
* view2DState: ol.View2DState,
* viewHints: Array.<number>}}

View File

@@ -617,6 +617,7 @@ ol.Map.prototype.renderFrame_ = function(time) {
postRenderFunctions: [],
size: size,
tileQueue: this.tileQueue_,
tileUsage: {},
view2DState: view2DState,
viewHints: viewHints,
time: time

View File

@@ -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.<number, Object.<string, ol.Tile>>} */
var tilesToDrawByZ = {};
tilesToDrawByZ[z] = {};

View File

@@ -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_) &&

View File

@@ -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.<string, Array.<ol.TileRange>>} */
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);

View File

@@ -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.<string, Array.<ol.TileRange>>} */
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)
]);
}

View File

@@ -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_);
};