Use object literals and use generic tile layer

This commit is contained in:
Tom Payne
2012-09-27 12:41:45 +02:00
parent 5ddbf17c8d
commit 65b8e0f915
37 changed files with 803 additions and 646 deletions

158
src/ol/source/bingmaps.js Normal file
View File

@@ -0,0 +1,158 @@
goog.provide('ol.source.BingMaps');
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.source.TileSource');
goog.require('ol.tilegrid.XYZ');
/**
* @enum {string}
*/
ol.BingMapsStyle = {
AERIAL: 'Aerial',
AERIAL_WITH_LABELS: 'AerialWithLabels',
ROAD: 'Road',
ORDNANCE_SURVEY: 'OrdnanceSurvey',
COLLINS_BART: 'CollinsBart'
};
/**
* @typedef {{culture: (string|undefined),
* key: string,
* style: ol.BingMapsStyle}}
*/
ol.source.BingMapsOptions;
/**
* @constructor
* @extends {ol.source.TileSource}
* @param {ol.source.BingMapsOptions} bingMapsOptions Bing Maps options.
*/
ol.source.BingMaps = function(bingMapsOptions) {
goog.base(this, {
projection: ol.Projection.getFromCode('EPSG:3857')
});
/**
* @private
* @type {string}
*/
this.culture_ = goog.isDef(bingMapsOptions.culture) ?
bingMapsOptions.culture : 'en-us';
/**
* @private
* @type {boolean}
*/
this.ready_ = false;
var uri = new goog.Uri(
'http://dev.virtualearth.net/REST/v1/Imagery/Metadata/' +
bingMapsOptions.style);
var jsonp = new goog.net.Jsonp(uri, 'jsonp');
jsonp.send({
'include': 'ImageryProviders',
'key': bingMapsOptions.key
}, goog.bind(this.handleImageryMetadataResponse, this));
};
goog.inherits(ol.source.BingMaps, ol.source.TileSource);
/**
* @param {BingMapsImageryMetadataResponse} response Response.
*/
ol.source.BingMaps.prototype.handleImageryMetadataResponse =
function(response) {
goog.asserts.assert(
response.authenticationResultCode == 'ValidCredentials');
goog.asserts.assert(response.statusCode == 200);
goog.asserts.assert(response.statusDescription == 'OK');
var brandLogoUri = response.brandLogoUri;
var copyright = response.copyright;
goog.asserts.assert(response.resourceSets.length == 1);
var resourceSet = response.resourceSets[0];
goog.asserts.assert(resourceSet.resources.length == 1);
var resource = resourceSet.resources[0];
var zoomMin = resource.zoomMin;
var zoomMax = resource.zoomMax;
var tileSize = new ol.Size(resource.imageWidth, resource.imageHeight);
var tileGrid = new ol.tilegrid.XYZ({
maxZoom: zoomMax,
tileSize: tileSize
});
this.tileGrid = tileGrid;
this.tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform(
function(tileCoord) {
if (tileCoord.z < zoomMin || zoomMax < tileCoord.z) {
return null;
}
var n = 1 << tileCoord.z;
var y = -tileCoord.y - 1;
if (y < 0 || n <= y) {
return null;
} else {
var x = goog.math.modulo(tileCoord.x, n);
return new ol.TileCoord(tileCoord.z, x, y);
}
},
ol.TileUrlFunction.createFromTileUrlFunctions(
goog.array.map(
resource.imageUrlSubdomains,
function(subdomain) {
var imageUrl = resource.imageUrl
.replace('{subdomain}', subdomain)
.replace('{culture}', this.culture_);
return function(tileCoord) {
if (goog.isNull(tileCoord)) {
return undefined;
} else {
return imageUrl.replace(
'{quadkey}', tileCoord.quadKey());
}
};
})));
var projection = ol.Projection.getFromCode('EPSG:4326');
var attributions = goog.array.map(
resource.imageryProviders,
function(imageryProvider) {
var html = imageryProvider.attribution;
var coverageAreas = goog.array.map(
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);
});
return new ol.Attribution(html, coverageAreas, projection);
});
this.setAttributions(attributions);
this.ready_ = true;
this.dispatchLoadEvent();
};
/**
* @inheritDoc
*/
ol.source.BingMaps.prototype.isReady = function() {
return this.ready_;
};

61
src/ol/source/mapquest.js Normal file
View File

@@ -0,0 +1,61 @@
goog.provide('ol.source.MapQuestOSM');
goog.provide('ol.source.MapQuestOpenAerial');
goog.require('ol.Attribution');
goog.require('ol.source.XYZ');
/**
* @constructor
* @extends {ol.source.XYZ}
*/
ol.source.MapQuestOSM = function() {
var attributions = [
new ol.Attribution(
'Tiles Courtesy of ' +
'<a href="http://www.mapquest.com/" target="_blank">MapQuest</a> ' +
'<img src="http://developer.mapquest.com/content/osm/mq_logo.png">'),
new ol.Attribution(
'Data &copy; ' +
'<a href="http://www.openstreetmap.org">OpenStreetMap</a> ' +
'contributors, ' +
'<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC BY-SA</a>')
];
goog.base(this, {
attributions: attributions,
maxZoom: 28,
url: 'http://otile{1-4}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg'
});
};
goog.inherits(ol.source.MapQuestOSM, ol.source.XYZ);
/**
* @constructor
* @extends {ol.source.XYZ}
*/
ol.source.MapQuestOpenAerial = function() {
var attributions = [
new ol.Attribution(
'Tiles Courtesy of ' +
'<a href="http://www.mapquest.com/" target="_blank">MapQuest</a> ' +
'<img src="http://developer.mapquest.com/content/osm/mq_logo.png">'),
new ol.Attribution(
'Portions Courtesy NASA/JPL-Caltech and ' +
'U.S. Depart. of Agriculture, Farm Service Agency')
];
goog.base(this, {
attributions: attributions,
maxZoom: 18,
url: 'http://oatile{1-4}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg'
});
};
goog.inherits(ol.source.MapQuestOpenAerial, ol.source.XYZ);

View File

@@ -0,0 +1,25 @@
goog.provide('ol.source.OpenStreetMap');
goog.require('ol.source.XYZ');
/**
* @constructor
* @extends {ol.source.XYZ}
*/
ol.source.OpenStreetMap = function() {
var attribution = new ol.Attribution(
'&copy; <a href="http://www.openstreetmap.org">OpenStreetMap</a> ' +
'contributors, ' +
'<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC BY-SA</a>');
goog.base(this, {
attributions: [attribution],
maxZoom: 18,
url: 'http://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'
});
};
goog.inherits(ol.source.OpenStreetMap, ol.source.XYZ);

119
src/ol/source/source.js Normal file
View File

@@ -0,0 +1,119 @@
goog.provide('ol.source.Source');
goog.require('goog.events.EventTarget');
goog.require('goog.events.EventType');
goog.require('goog.functions');
goog.require('ol.Attribution');
goog.require('ol.Extent');
goog.require('ol.Projection');
goog.require('ol.TileUrlFunction');
/**
* @typedef {{attribtions: (Array.<ol.Attribution>|undefined),
* extent: (ol.Extent|undefined),
* projection: (ol.Projection|undefined)}}
*/
ol.source.SourceOptions;
/**
* @constructor
* @extends {goog.events.EventTarget}
* @param {ol.source.SourceOptions} sourceOptions Source options.
*/
ol.source.Source = function(sourceOptions) {
goog.base(this);
/**
* @private
* @type {ol.Projection}
*/
this.projection_ = goog.isDef(sourceOptions.projection) ?
sourceOptions.projection : null;
/**
* @private
* @type {ol.Extent}
*/
this.extent_ = goog.isDef(sourceOptions.extent) ?
sourceOptions.extent : sourceOptions.projection.getExtent();
/**
* @private
* @type {Array.<ol.Attribution>}
*/
this.attributions_ = goog.isDef(sourceOptions.attributions) ?
sourceOptions.attributions : null;
};
goog.inherits(ol.source.Source, goog.events.EventTarget);
/**
*/
ol.source.Source.prototype.dispatchLoadEvent = function() {
this.dispatchEvent(goog.events.EventType.LOAD);
};
/**
* @return {Array.<ol.Attribution>} Attributions.
*/
ol.source.Source.prototype.getAttributions = function() {
return this.attributions_;
};
/**
* @return {ol.Extent} Extent.
*/
ol.source.Source.prototype.getExtent = function() {
return this.extent_;
};
/**
* @return {ol.Projection} Projection.
*/
ol.source.Source.prototype.getProjection = function() {
return this.projection_;
};
/**
* @return {Array.<number>|undefined} Resolutions.
*/
ol.source.Source.prototype.getResolutions = goog.abstractMethod;
/**
* @return {boolean} Is ready.
*/
ol.source.Source.prototype.isReady = goog.functions.TRUE;
/**
* @param {Array.<ol.Attribution>} attributions Attributions.
*/
ol.source.Source.prototype.setAttributions = function(attributions) {
this.attributions_ = attributions;
};
/**
* @param {ol.Extent} extent Extent.
*/
ol.source.Source.prototype.setExtent = function(extent) {
this.extent_ = extent;
};
/**
* @param {ol.Projection} projection Projetion.
*/
ol.source.Source.prototype.setProjection = function(projection) {
this.projection_ = projection;
};

97
src/ol/source/stamen.js Normal file
View File

@@ -0,0 +1,97 @@
// FIXME Configure minZoom when supported by TileGrid
goog.provide('ol.source.Stamen');
goog.require('ol.source.XYZ');
/**
* @enum {string}
*/
ol.source.StamenFlavor = {
TERRAIN_BACKGROUND: 'background',
TERRAIN_LABELS: 'labels',
TERRAIN_LINES: 'lines',
TONER_2010: '2010',
TONER_2011: '2011',
TONER_2011_LABELS: '2011-labels',
TONER_2011_LINES: '2011-lines',
TONER_2011_LITE: '2011-lite',
TONER_BACKGROUND: 'background',
TONER_HYBRID: 'hybrid',
TONER_LABELS: 'labels',
TONER_LINES: 'lines',
TONER_LITE: 'lite'
};
/**
* @typedef {{flavor: ol.source.StamenFlavor,
* provider: ol.source.StamenProvider}}
*/
ol.source.StamenOptions;
/**
* @enum {string}
*/
ol.source.StamenProvider = {
TERRAIN: 'terrain',
TONER: 'toner',
WATERCOLOR: 'watercolor'
};
/**
* @type {Object.<ol.source.StamenProvider,
* {type: string, minZoom: number, maxZoom: number}>}
*/
ol.source.StamenProviderConfig = {};
ol.source.StamenProviderConfig[ol.source.StamenProvider.TERRAIN] = {
type: 'jpg',
minZoom: 4,
maxZoom: 18
};
ol.source.StamenProviderConfig[ol.source.StamenProvider.TONER] = {
type: 'png',
minZoom: 0,
maxZoom: 20
};
ol.source.StamenProviderConfig[ol.source.StamenProvider.WATERCOLOR] = {
type: 'jpg',
minZoom: 3,
maxZoom: 16
};
/**
* @constructor
* @extends {ol.source.XYZ}
* @param {ol.source.StamenOptions} stamenOptions Stamen options.
*/
ol.source.Stamen = function(stamenOptions) {
var attribution = new ol.Attribution(
'Map tiles by <a href="http://stamen.com">Stamen Design</a>, ' +
'under ' +
'<a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. ' +
'Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, ' +
'under ' +
'<a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.');
var layer = stamenOptions.provider;
if (goog.isDef(stamenOptions.flavor)) {
layer += '-' + stamenOptions.flavor;
}
var config = ol.source.StamenProviderConfig[stamenOptions.provider];
goog.base(this, {
attributions: [attribution],
maxZoom: config.maxZoom,
url: 'http://{a-d}.tile.stamen.com/' + layer + '/{z}/{x}/{y}.' + config.type
});
};
goog.inherits(ol.source.Stamen, ol.source.XYZ);

153
src/ol/source/tilejson.js Normal file
View File

@@ -0,0 +1,153 @@
// FIXME add some error checking
// FIXME check order of async callbacks
// FIXME use minzoom when supported by ol.tilegrid.TileGrid
/**
* @see http://mapbox.com/developers/api/
*/
goog.provide('ol.source.TileJSON');
goog.provide('ol.tilejson');
goog.require('goog.asserts');
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.TileSource');
/**
* @typedef {{uri: string}}
*/
ol.source.TileJSONOptions;
/**
* @private
* @type {Array.<TileJSON>}
*/
ol.tilejson.grids_ = [];
/**
* @param {TileJSON} tileJSON Tile JSON.
*/
var grid = function(tileJSON) {
ol.tilejson.grids_.push(tileJSON);
};
goog.exportSymbol('grid', grid);
/**
* @constructor
* @extends {ol.source.TileSource}
* @param {ol.source.TileJSONOptions} tileJsonOptions TileJSON optios.
*/
ol.source.TileJSON = function(tileJsonOptions) {
goog.base(this, {
projection: ol.Projection.getFromCode('EPSG:3857')
});
/**
* @private
* @type {boolean}
*/
this.ready_ = false;
/**
* @private
* @type {!goog.async.Deferred}
*/
this.deferred_ =
goog.net.jsloader.load(tileJsonOptions.uri, {cleanupWhenDone: true});
this.deferred_.addCallback(this.handleTileJSONResponse, this);
};
goog.inherits(ol.source.TileJSON, ol.source.TileSource);
/**
* @protected
*/
ol.source.TileJSON.prototype.handleTileJSONResponse = function() {
var tileJSON = ol.tilejson.grids_.pop();
var epsg4326Projection = ol.Projection.getFromCode('EPSG:4326');
var epsg4326Extent, extent;
if (goog.isDef(tileJSON.bounds)) {
var bounds = tileJSON.bounds;
epsg4326Extent = new ol.Extent(
bounds[0], bounds[1], bounds[2], bounds[3]);
extent = epsg4326Extent.transform(
ol.Projection.getTransform(epsg4326Projection, this.getProjection()));
this.setExtent(extent);
} else {
epsg4326Extent = null;
extent = null;
}
var scheme = goog.isDef(tileJSON.scheme) || 'xyz';
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 tileGrid = new ol.tilegrid.XYZ({
maxZoom: maxzoom
});
this.tileGrid = tileGrid;
this.tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform(
function(tileCoord) {
if (tileCoord.z < minzoom || maxzoom < tileCoord.z) {
return null;
}
var n = 1 << tileCoord.z;
var y = -tileCoord.y - 1;
if (y < 0 || n <= y) {
return null;
}
var x = goog.math.modulo(tileCoord.x, n);
if (!goog.isNull(extent)) {
var tileExtent = tileGrid.getTileCoordExtent(
new ol.TileCoord(tileCoord.z, x, tileCoord.y));
if (!tileExtent.intersects(extent)) {
return null;
}
}
return new ol.TileCoord(tileCoord.z, x, y);
},
ol.TileUrlFunction.createFromTemplates(tileJSON.tiles));
if (goog.isDef(tileJSON.attribution)) {
var coverageAreas = [
new ol.TileCoverageArea(tileGrid, epsg4326Extent, minzoom, maxzoom)
];
var coverageAreaProjection = epsg4326Projection;
this.setAttributions([
new ol.Attribution(
tileJSON.attribution, coverageAreas, coverageAreaProjection)
]);
}
this.ready_ = true;
this.dispatchLoadEvent();
};
/**
* @inheritDoc
*/
ol.source.TileJSON.prototype.isReady = function() {
return this.ready_;
};

118
src/ol/source/tilesource.js Normal file
View File

@@ -0,0 +1,118 @@
goog.provide('ol.source.TileSource');
goog.provide('ol.source.TileSourceOptions');
goog.require('ol.Attribution');
goog.require('ol.Extent');
goog.require('ol.Projection');
goog.require('ol.Tile');
goog.require('ol.TileCoord');
goog.require('ol.TileUrlFunction');
goog.require('ol.TileUrlFunctionType');
goog.require('ol.source.Source');
goog.require('ol.tilegrid.TileGrid');
/**
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
* crossOrigin: (string|undefined),
* extent: (ol.Extent|undefined),
* projection: (ol.Projection|undefined),
* tileGrid: (ol.tilegrid.TileGrid|undefined),
* tileUrlFunction: (ol.TileUrlFunctionType|undefined)}}
*/
ol.source.TileSourceOptions;
/**
* @constructor
* @extends {ol.source.Source}
* @param {ol.source.TileSourceOptions} tileSourceOptions Tile source options.
*/
ol.source.TileSource = function(tileSourceOptions) {
goog.base(this, {
attributions: tileSourceOptions.attributions,
extent: tileSourceOptions.extent,
projection: tileSourceOptions.projection
});
/**
* @protected
* @type {ol.tilegrid.TileGrid}
*/
this.tileGrid = goog.isDef(tileSourceOptions.tileGrid) ?
tileSourceOptions.tileGrid : null;
/**
* @protected
* @type {ol.TileUrlFunctionType}
*/
this.tileUrlFunction = goog.isDef(tileSourceOptions.tileUrlFunction) ?
tileSourceOptions.tileUrlFunction :
ol.TileUrlFunction.nullTileUrlFunction;
/**
* @private
* @type {?string}
*/
this.crossOrigin_ = goog.isDef(tileSourceOptions.crossOrigin) ?
tileSourceOptions.crossOrigin : 'anonymous';
/**
* @private
* @type {Object.<string, ol.Tile>}
* FIXME will need to expire elements from this cache
* FIXME see elemoine's work with goog.structs.LinkedMap
*/
this.tileCache_ = {};
};
goog.inherits(ol.source.TileSource, ol.source.Source);
/**
* @inheritDoc
*/
ol.source.TileSource.prototype.getResolutions = function() {
return this.tileGrid.getResolutions();
};
/**
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @return {ol.Tile} Tile.
*/
ol.source.TileSource.prototype.getTile = function(tileCoord) {
var key = tileCoord.toString();
if (goog.object.containsKey(this.tileCache_, key)) {
return this.tileCache_[key];
} else {
var tileUrl = this.getTileCoordUrl(tileCoord);
var tile;
if (goog.isDef(tileUrl)) {
tile = new ol.Tile(tileCoord, tileUrl, this.crossOrigin_);
} else {
tile = null;
}
this.tileCache_[key] = tile;
return tile;
}
};
/**
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @return {string|undefined} Tile URL.
*/
ol.source.TileSource.prototype.getTileCoordUrl = function(tileCoord) {
return this.tileUrlFunction(tileCoord);
};
/**
* @return {ol.tilegrid.TileGrid} Tile grid.
*/
ol.source.TileSource.prototype.getTileGrid = function() {
return this.tileGrid;
};

109
src/ol/source/xyz.js Normal file
View File

@@ -0,0 +1,109 @@
// FIXME add minZoom support
goog.provide('ol.source.XYZ');
goog.provide('ol.source.XYZOptions');
goog.require('goog.math');
goog.require('ol.Attribution');
goog.require('ol.Coordinate');
goog.require('ol.Projection');
goog.require('ol.Size');
goog.require('ol.TileCoord');
goog.require('ol.TileUrlFunction');
goog.require('ol.TileUrlFunctionType');
goog.require('ol.source.TileSource');
goog.require('ol.tilegrid.XYZ');
/**
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
* crossOrigin: (string|undefined),
* extent: (ol.Extent|undefined),
* maxZoom: number,
* tileUrlFunction: (ol.TileUrlFunctionType|undefined),
* url: (string|undefined),
* urls: (Array.<string>|undefined)}}
*/
ol.source.XYZOptions;
/**
* @constructor
* @extends {ol.source.TileSource}
* @param {ol.source.XYZOptions} xyzOptions XYZ options.
*/
ol.source.XYZ = function(xyzOptions) {
/**
* @type {ol.TileUrlFunctionType}
*/
var tileUrlFunction = ol.TileUrlFunction.nullTileUrlFunction;
// FIXME use goog.nullFunction ?
if (goog.isDef(xyzOptions.tileUrlFunction)) {
tileUrlFunction = xyzOptions.tileUrlFunction;
} else if (goog.isDef(xyzOptions.urls)) {
tileUrlFunction = ol.TileUrlFunction.createFromTemplates(xyzOptions.urls);
} else if (goog.isDef(xyzOptions.url)) {
tileUrlFunction = ol.TileUrlFunction.createFromTemplate(xyzOptions.url);
}
var tileGrid = new ol.tilegrid.XYZ({
maxZoom: xyzOptions.maxZoom
});
// FIXME factor out common code
var extent = xyzOptions.extent;
if (goog.isDefAndNotNull(extent)) {
tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform(
function(tileCoord) {
if (xyzOptions.maxZoom < tileCoord.z) {
return null;
}
var n = 1 << tileCoord.z;
var y = -tileCoord.y - 1;
if (y < 0 || n <= y) {
return null;
}
var x = goog.math.modulo(tileCoord.x, n);
var tileExtent = tileGrid.getTileCoordExtent(
new ol.TileCoord(tileCoord.z, x, tileCoord.y));
// FIXME we shouldn't need a typecast here
if (!tileExtent.intersects(/** @type {ol.Extent} */ (extent))) {
return null;
}
return new ol.TileCoord(tileCoord.z, x, y);
},
tileUrlFunction);
} else {
tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform(
function(tileCoord) {
if (xyzOptions.maxZoom < tileCoord.z) {
return null;
}
var n = 1 << tileCoord.z;
var y = -tileCoord.y - 1;
if (y < 0 || n <= y) {
return null;
} else {
var x = goog.math.modulo(tileCoord.x, n);
return new ol.TileCoord(tileCoord.z, x, y);
}
},
tileUrlFunction);
}
goog.base(this, {
attributions: xyzOptions.attributions,
crossOrigin: xyzOptions.crossOrigin,
extent: xyzOptions.extent,
projection: ol.Projection.getFromCode('EPSG:3857'),
tileGrid: tileGrid,
tileUrlFunction: tileUrlFunction
});
};
goog.inherits(ol.source.XYZ, ol.source.TileSource);