Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge from master

  • Loading branch information...
commit 74281d2b009edb635d499b95e58585df757fccd5 2 parents 8a38f9a + bb51709
@tschaub tschaub authored
Showing with 1,037 additions and 596 deletions.
  1. +2 −2 build.py
  2. +2 −4 examples/canvas-tiles.js
  3. +4 −1 examples/side-by-side.html
  4. +23 −0 examples/side-by-side.js
  5. +3 −1 examples/two-layers.html
  6. +8 −0 examples/two-layers.js
  7. +5 −3 pake.py
  8. +14 −0 src/objectliterals.exports
  9. +4 −0 src/ol/animation.exports
  10. +34 −1 src/ol/animation.js
  11. +24 −26 src/ol/attribution.js
  12. +21 −0 src/ol/canvas/canvas.js
  13. +6 −5 src/ol/color.js
  14. +111 −357 src/ol/control/attributioncontrol.js
  15. +10 −2 src/ol/control/zoomcontrol.js
  16. +0 −55 src/ol/coveragearea.js
  17. +9 −0 src/ol/easing.js
  18. +2 −0  src/ol/framestate.js
  19. +8 −1 src/ol/interaction/keyboardzoominteraction.js
  20. +3 −1 src/ol/map.exports
  21. +21 −4 src/ol/map.js
  22. +11 −0 src/ol/rectangle.js
  23. +37 −0 src/ol/renderer/canvas/canvaslayerrenderer.js
  24. +177 −0 src/ol/renderer/canvas/canvasmaprenderer.js
  25. +10 −1 src/ol/renderer/canvas/canvasrenderer.js
  26. +236 −0 src/ol/renderer/canvas/canvastilelayerrenderer.js
  27. +9 −0 src/ol/renderer/dom/domlayerrenderer.js
  28. +0 −9 src/ol/renderer/dom/dommaprenderer.js
  29. +2 −0  src/ol/renderer/dom/domtilelayerrenderer.js
  30. +26 −0 src/ol/renderer/layerrenderer.js
  31. +2 −1  src/ol/renderer/webgl/webglmaprenderer.js
  32. +2 −1  src/ol/renderer/webgl/webgltilelayerrenderer.js
  33. +21 −7 src/ol/source/bingmapssource.js
  34. +19 −0 src/ol/source/stamen.exports
  35. +3 −9 src/ol/source/stamensource.js
  36. +16 −12 src/ol/source/tilejsonsource.js
  37. +0 −69 src/ol/tilecoveragearea.js
  38. +1 −0  src/ol/tilegrid/tilegrid.exports
  39. +13 −11 src/ol/tilegrid/tilegrid.js
  40. +1 −0  src/ol/tilegrid/xyztilegrid.exports
  41. +3 −9 src/ol/tilegrid/xyztilegrid.js
  42. +1 −0  src/ol/view2d.exports
  43. +13 −4 src/ol/view2d.js
  44. +1 −0  test/ol.html
  45. +71 −0 test/spec/ol/color.test.js
  46. +48 −0 test/spec/ol/map.test.js
View
4 build.py
@@ -192,13 +192,13 @@ def build_lint_src_timestamp(t):
limited_doc_files = [path
for path in ifind('externs', 'build/src/external/externs')
if path.endswith('.js')]
- t.run('%(GJSLINT)s', '--strict', '--limited_doc_files=%s' % (','.join(limited_doc_files),), SRC, INTERNAL_SRC, EXTERNAL_SRC, EXAMPLES_SRC)
+ t.run('%(GJSLINT)s', '--strict', '--limited_doc_files=%s' % (','.join(limited_doc_files),), t.newer(SRC, INTERNAL_SRC, EXTERNAL_SRC, EXAMPLES_SRC))
t.touch()
@target('build/lint-spec-timestamp', SPEC)
def build_lint_spec_timestamp(t):
- t.run('%(GJSLINT)s', SPEC)
+ t.run('%(GJSLINT)s', t.newer(SPEC))
t.touch()
View
6 examples/canvas-tiles.js
@@ -5,14 +5,12 @@ goog.require('ol.Projection');
goog.require('ol.RendererHint');
goog.require('ol.layer.TileLayer');
goog.require('ol.source.DebugTileSource');
-goog.require('ol.source.Stamen');
+goog.require('ol.source.OpenStreetMap');
var layers = new ol.Collection([
new ol.layer.TileLayer({
- source: new ol.source.Stamen({
- provider: ol.source.StamenProvider.WATERCOLOR
- })
+ source: new ol.source.OpenStreetMap()
}),
new ol.layer.TileLayer({
source: new ol.source.DebugTileSource({
View
5 examples/side-by-side.html
@@ -16,19 +16,22 @@
</head>
<body>
<h1 id="title">Side-by-side example</h1>
- <div id="shortdesc">Side-by-side DOM and WebGL sync'ed maps.</div>
+ <div id="shortdesc">Side-by-side DOM, WebGL and Canvas sync'ed maps.</div>
<table>
<tr>
<th>DOM</th>
<th>WebGL</th>
+ <th>Canvas</th>
</tr>
<tr>
<td><div id="domMap" class="map"></div></td>
<td><div id="webglMap" class="map"></div></td>
+ <td><div id="canvasMap" class="map"></div></td>
</tr>
<tr>
<td><div id="domMousePosition" class="mouseposition"></div></td>
<td><div id="webglMousePosition" class="mouseposition"></div></td>
+ <td><div id="canvasMousePosition" class="mouseposition"></div></td>
</tr>
</table>
<table>
View
23 examples/side-by-side.js
@@ -62,6 +62,22 @@ webglMap.getControls().push(new ol.control.MousePosition({
undefinedHTML: '&nbsp;'
}));
+var canvasMap = new ol.Map({
+ renderer: ol.RendererHint.CANVAS,
+ target: 'canvasMap'
+});
+if (canvasMap !== null) {
+ canvasMap.bindTo('layers', domMap);
+ canvasMap.bindTo('view', domMap);
+}
+
+canvasMap.getControls().push(new ol.control.MousePosition({
+ coordinateFormat: ol.Coordinate.toStringHDMS,
+ projection: ol.Projection.getFromCode('EPSG:4326'),
+ target: document.getElementById('canvasMousePosition'),
+ undefinedHtml: '&nbsp;'
+}));
+
var keyboardInteraction = new ol.interaction.Keyboard();
keyboardInteraction.addCallback('0', function() {
layer.setBrightness(0);
@@ -94,11 +110,13 @@ keyboardInteraction.addCallback('j', function() {
var bounce = ol.animation.createBounce(2 * view.getResolution());
domMap.addPreRenderFunction(bounce);
webglMap.addPreRenderFunction(bounce);
+ canvasMap.addPreRenderFunction(bounce);
});
keyboardInteraction.addCallback('l', function() {
var panFrom = ol.animation.createPanFrom(view.getCenter());
domMap.addPreRenderFunction(panFrom);
webglMap.addPreRenderFunction(panFrom);
+ canvasMap.addPreRenderFunction(panFrom);
view.setCenter(LONDON);
});
keyboardInteraction.addCallback('L', function() {
@@ -111,12 +129,14 @@ keyboardInteraction.addCallback('L', function() {
var preRenderFunctions = [bounce, panFrom, spin];
domMap.addPreRenderFunctions(preRenderFunctions);
webglMap.addPreRenderFunctions(preRenderFunctions);
+ canvasMap.addPreRenderFunctions(preRenderFunctions);
view.setCenter(LONDON);
});
keyboardInteraction.addCallback('m', function() {
var panFrom = ol.animation.createPanFrom(view.getCenter(), 1000);
domMap.addPreRenderFunction(panFrom);
webglMap.addPreRenderFunction(panFrom);
+ canvasMap.addPreRenderFunction(panFrom);
view.setCenter(MOSCOW);
});
keyboardInteraction.addCallback('M', function() {
@@ -129,6 +149,7 @@ keyboardInteraction.addCallback('M', function() {
var preRenderFunctions = [bounce, panFrom, spin];
domMap.addPreRenderFunctions(preRenderFunctions);
webglMap.addPreRenderFunctions(preRenderFunctions);
+ canvasMap.addPreRenderFunctions(preRenderFunctions);
view.setCenter(MOSCOW);
});
keyboardInteraction.addCallback('o', function() {
@@ -154,10 +175,12 @@ keyboardInteraction.addCallback('x', function() {
var spin = ol.animation.createSpin(2000, 2);
domMap.addPreRenderFunction(spin);
webglMap.addPreRenderFunction(spin);
+ canvasMap.addPreRenderFunction(spin);
});
keyboardInteraction.addCallback('X', function() {
var spin = ol.animation.createSpin(2000, -2);
domMap.addPreRenderFunction(spin);
webglMap.addPreRenderFunction(spin);
+ canvasMap.addPreRenderFunction(spin);
});
domMap.getInteractions().push(keyboardInteraction);
View
4 examples/two-layers.html
@@ -16,15 +16,17 @@
</head>
<body>
<h1 id="title">Two-layer example</h1>
- <div id="shortdesc">Sync'ed DOM and WebGL maps with two layers.</div>
+ <div id="shortdesc">Sync'ed DOM, WebGL and Canvas maps with two layers.</div>
<table>
<tr>
<th>DOM</th>
<th>WebGL</th>
+ <th>Canvas</th>
</tr>
<tr>
<td><div id="domMap" class="map"></div></td>
<td><div id="webglMap" class="map"></div></td>
+ <td><div id="canvasMap" class="map"></div></td>
</tr>
</table>
<div id="docs">
View
8 examples/two-layers.js
@@ -40,3 +40,11 @@ var domMap = new ol.Map({
});
domMap.bindTo('layers', webglMap);
domMap.bindTo('view', webglMap);
+
+
+var canvasMap = new ol.Map({
+ renderer: ol.RendererHint.CANVAS,
+ target: 'canvasMap'
+});
+canvasMap.bindTo('layers', webglMap);
+canvasMap.bindTo('view', webglMap);
View
8 pake.py
@@ -152,9 +152,7 @@ def download(self, url, md5=None):
content = urllib2.urlopen(url).read()
if md5 and hashlib.md5(content).hexdigest() != md5:
raise BuildError(self, 'corrupt download')
- # FIXME Python on Windoze corrupts the content when writing it
- # FIXME probably something to do with encodings
- with open(self.name, 'w') as f:
+ with open(self.name, 'wb') as f:
f.write(content)
def error(self, message):
@@ -178,6 +176,10 @@ def makedirs(self, path):
self.info('mkdir -p %s', path)
os.makedirs(path)
+ def newer(self, *args):
+ args = flatten_expand_list(args)
+ return [arg for arg in args if targets.get(arg).timestamp > self.timestamp]
+
def output(self, *args, **kwargs):
args = flatten_expand_list(args)
self.info(' '.join(args))
View
14 src/objectliterals.exports
@@ -51,6 +51,10 @@
@exportObjectLiteralProperty ol.source.BingMapsOptions.key string
@exportObjectLiteralProperty ol.source.BingMapsOptions.style ol.BingMapsStyle
+@exportObjectLiteral ol.source.StamenOptions
+@exportObjectLiteralProperty ol.source.StamenOptions.flavor string|undefined
+@exportObjectLiteralProperty ol.source.StamenOptions.provider string
+
@exportObjectLiteral ol.source.TiledWMSOptions
@exportObjectLiteralProperty ol.source.TiledWMSOptions.attributions Array.<ol.Attribution>|undefined
@exportObjectLiteralProperty ol.source.TiledWMSOptions.params Object
@@ -63,6 +67,16 @@
@exportObjectLiteralProperty ol.source.TiledWMSOptions.url string|undefined
@exportObjectLiteralProperty ol.source.TiledWMSOptions.urls Array.<string>|undefined
+@exportObjectLiteral ol.tilegrid.TileGridOptions
+@exportObjectLiteralProperty ol.tilegrid.TileGridOptions.extent ol.Extent|undefined
+@exportObjectLiteralProperty ol.tilegrid.TileGridOptions.origin ol.Coordinate|undefined
+@exportObjectLiteralProperty ol.tilegrid.TileGridOptions.origins Array.<ol.Coordinate>|undefined
+@exportObjectLiteralProperty ol.tilegrid.TileGridOptions.resolutions !Array.<number>
+@exportObjectLiteralProperty ol.tilegrid.TileGridOptions.tileSize ol.Size|undefined
+
+@exportObjectLiteral ol.tilegrid.XYZOptions
+@exportObjectLiteralProperty ol.tilegrid.XYZOptions.maxZoom number
+
@exportObjectLiteral ol.View2DOptions
@exportObjectLiteralProperty ol.View2DOptions.center ol.Coordinate|undefined
@exportObjectLiteralProperty ol.View2DOptions.maxResolution number|undefined
View
4 src/ol/animation.exports
@@ -0,0 +1,4 @@
+@exportSymbol ol.animation
+@exportProperty ol.animation.createBounce
+@exportProperty ol.animation.createPanFrom
+@exportProperty ol.animation.createSpin
View
35 src/ol/animation.js
@@ -1,10 +1,10 @@
// FIXME works for View2D only
+// FIXME dependency on ol.View2D suppressed to prevent dependency loop
goog.provide('ol.animation');
goog.require('goog.fx.easing');
goog.require('ol.PreRenderFunction');
-goog.require('ol.View2D');
goog.require('ol.easing');
@@ -107,3 +107,36 @@ ol.animation.createSpin =
}
};
};
+
+
+/**
+ * @param {number} sourceResolution Source resolution.
+ * @param {number=} opt_duration Duration.
+ * @param {number=} opt_start Start.
+ * @param {function(number): number=} opt_easingFunction Easing function.
+ * @return {ol.PreRenderFunction} Pre-render function.
+ */
+ol.animation.createZoomFrom =
+ function(sourceResolution, opt_duration, opt_start, opt_easingFunction) {
+ var start = goog.isDef(opt_start) ? opt_start : Date.now();
+ var duration = goog.isDef(opt_duration) ? opt_duration : 1000;
+ var easingFunction = goog.isDef(opt_easingFunction) ?
+ opt_easingFunction : ol.easing.linear;
+ return function(map, frameState) {
+ if (frameState.time < start) {
+ frameState.animate = true;
+ frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
+ return true;
+ } else if (frameState.time < start + duration) {
+ var delta = 1 - easingFunction((frameState.time - start) / duration);
+ var deltaResolution =
+ sourceResolution - frameState.view2DState.resolution;
+ frameState.animate = true;
+ frameState.view2DState.resolution += delta * deltaResolution;
+ frameState.viewHints[ol.ViewHint.ANIMATING] += 1;
+ return true;
+ } else {
+ return false;
+ }
+ };
+};
View
50 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.<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>}
- */
- this.coverageAreas_ = opt_coverageAreas || null;
-
- /**
- * @private
- * @type {ol.Projection}
+ * @type {Object.<string, Array.<ol.TileRange>>}
*/
- this.projection_ = opt_projection || null;
+ this.tileRanges_ = opt_tileRanges || 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
21 src/ol/canvas/canvas.js
@@ -0,0 +1,21 @@
+goog.provide('ol.canvas');
+
+goog.require('goog.dom');
+goog.require('goog.dom.TagName');
+
+
+/**
+ * @return {boolean} Is supported.
+ */
+ol.canvas.isSupported = function() {
+ if (!('HTMLCanvasElement' in goog.global)) {
+ return false;
+ }
+ try {
+ var canvas = /** @type {HTMLCanvasElement} */
+ (goog.dom.createElement(goog.dom.TagName.CANVAS));
+ return !goog.isNull(canvas.getContext('2d'));
+ } catch (e) {
+ return false;
+ }
+};
View
11 src/ol/color.js
@@ -1,6 +1,7 @@
goog.provide('ol.Color');
goog.require('goog.color');
+goog.require('goog.math');
@@ -9,29 +10,29 @@ goog.require('goog.color');
* @param {number} r Red, 0 to 255.
* @param {number} g Green, 0 to 255.
* @param {number} b Blue, 0 to 255.
- * @param {number} a Alpha, 0 (fully transparent) to 255 (fully opaque).
+ * @param {number} a Alpha, 0 (fully transparent) to 1 (fully opaque).
*/
ol.Color = function(r, g, b, a) {
/**
* @type {number}
*/
- this.r = r;
+ this.r = goog.math.clamp(r, 0, 255);
/**
* @type {number}
*/
- this.g = g;
+ this.g = goog.math.clamp(g, 0, 255);
/**
* @type {number}
*/
- this.b = b;
+ this.b = goog.math.clamp(b, 0, 255);
/**
* @type {number}
*/
- this.a = a;
+ this.a = goog.math.clamp(a, 0, 1);
};
View
468 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,404 +27,167 @@ ol.control.Attribution = function(attributionOptions) {
'class': 'ol-attribution'
}, this.ulElement_);
- /**
- * @private
- * @type {Object.<number, ?number>}
- */
- this.layerVisibleChangeListenerKeys_ = {};
-
- /**
- * @private
- * @type {Object.<number, Element>}
- */
- this.attributionElements_ = {};
+ goog.base(this, {
+ element: element,
+ map: attributionOptions.map,
+ target: attributionOptions.target
+ });
/**
* @private
- * @type {Object.<number, Array.<ol.CoverageArea>>}
+ * @type {boolean}
*/
- this.coverageAreass_ = {};
+ this.renderedVisible_ = true;
/**
* @private
- * @type {Array.<number>}
+ * @type {Object.<string, Element>}
*/
- this.mapListenerKeys_ = null;
+ this.attributionElements_ = {};
/**
* @private
- * @type {Array.<number>}
+ * @type {Object.<string, boolean>}
*/
- this.layersListenerKeys_ = null;
+ this.attributionElementRenderedVisible_ = {};
/**
* @private
- * @type {Array.<number>}
+ * @type {Array.<?number>}
*/
- this.viewListenerKeys_ = null;
-
- goog.base(this, {
- element: element,
- map: attributionOptions.map,
- target: attributionOptions.target
- });
+ 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
+ * @inheritDoc
*/
-ol.control.Attribution.prototype.createAttributionElementsForLayer_ =
- function(layer) {
-
- var source = layer.getSource();
- var attributions = source.getAttributions();
- if (goog.isNull(attributions)) {
- return;
+ol.control.Attribution.prototype.setMap = function(map) {
+ if (!goog.isNull(this.listenerKeys_)) {
+ goog.array.forEach(this.listenerKeys_, goog.events.unlistenByKey);
+ this.listenerKeys_ = null;
}
-
- 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.base(this, 'setMap', map);
+ if (!goog.isNull(map)) {
+ this.listenerKeys_ = [
+ goog.events.listen(map, ol.MapEventType.POSTRENDER,
+ this.handleMapPostrender, false, this)
+ ];
}
-
- 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
+ * @param {?Object.<string, Object.<string, ol.TileRange>>} tileUsage Tile
+ * usage.
*/
-ol.control.Attribution.prototype.getLayerAttributionVisiblities_ =
- function(layer, mapExtent, mapResolution, mapProjection) {
+ol.control.Attribution.prototype.updateElement_ = function(tileUsage) {
- 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);
+ if (goog.isNull(tileUsage)) {
+ if (this.renderedVisible_) {
+ goog.style.showElement(this.element, false);
+ this.renderedVisible_ = false;
+ }
+ return;
}
- var attributionVisibilities = {};
- goog.array.forEach(attributions, function(attribution) {
-
- var attributionKey = goog.getUid(attribution);
-
- var attributionVisible = true;
+ var map = this.getMap();
- 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);
- });
+ /** @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;
}
}
- 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);
- });
+ /** @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;
}
}
-
- 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)
- ];
+ /** @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];
}
-};
-
-/**
- * @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);
-
-};
-
-
-/**
- * @inheritDoc
- */
-ol.control.Attribution.prototype.setMap = function(map) {
- if (!goog.isNull(this.mapListenerKeys_)) {
- goog.array.forEach(this.mapListenerKeys_, goog.events.unlistenByKey);
- }
- 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.handleMapViewChanged();
- this.handleMapLayersChanged();
+ for (attributionKey in attributionsToRemove) {
+ goog.dom.removeNode(this.attributionElements_[attributionKey]);
+ delete this.attributionElements_[attributionKey];
+ delete this.attributionElementRenderedVisible_[attributionKey];
}
-};
-
-
-/**
- * @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
- */
-ol.control.Attribution.prototype.updateLayerAttributionsVisibility_ =
- function(layer) {
- 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);
- }
+ var renderVisible = !goog.array.isEmpty(attributionKeys);
+ if (this.renderedVisible_ != renderVisible) {
+ goog.style.showElement(this.element, renderVisible);
+ this.renderedVisible_ = renderVisible;
}
+
};
View
12 src/ol/control/zoomcontrol.js
@@ -11,6 +11,12 @@ goog.require('ol.Projection');
goog.require('ol.control.Control');
+/**
+ * @define {number} Zoom duration.
+ */
+ol.control.ZOOM_DURATION = 250;
+
+
/**
* @constructor
@@ -61,8 +67,9 @@ ol.control.Zoom.prototype.handleIn_ = function(browserEvent) {
// prevent #zoomIn anchor from getting appended to the url
browserEvent.preventDefault();
var map = this.getMap();
+ map.requestRenderFrame();
// FIXME works for View2D only
- map.getView().zoom(map, this.delta_);
+ map.getView().zoom(map, this.delta_, undefined, ol.control.ZOOM_DURATION);
};
@@ -74,6 +81,7 @@ ol.control.Zoom.prototype.handleOut_ = function(browserEvent) {
// prevent #zoomOut anchor from getting appended to the url
browserEvent.preventDefault();
var map = this.getMap();
+ map.requestRenderFrame();
// FIXME works for View2D only
- map.getView().zoom(map, -this.delta_);
+ map.getView().zoom(map, -this.delta_, undefined, ol.control.ZOOM_DURATION);
};
View
55 src/ol/coveragearea.js
@@ -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
9 src/ol/easing.js
@@ -5,6 +5,15 @@ goog.provide('ol.easing');
* @param {number} t Input between 0 and 1.
* @return {number} Output between 0 and 1.
*/
+ol.easing.linear = function(t) {
+ return t;
+};
+
+
+/**
+ * @param {number} t Input between 0 and 1.
+ * @return {number} Output between 0 and 1.
+ */
ol.easing.upAndDown = function(t) {
if (t < 0.5) {
return goog.fx.easing.inAndOut(2 * t);
View
2  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.<ol.PostRenderFunction>,
* size: ol.Size,
* tileQueue: ol.TileQueue,
+ * tileUsage: Object.<string, Object.<string, ol.TileRange>>,
* time: number,
* view2DState: ol.View2DState,
* viewHints: Array.<number>}}
View
9 src/ol/interaction/keyboardzoominteraction.js
@@ -8,6 +8,12 @@ goog.require('ol.View2D');
goog.require('ol.interaction.Interaction');
+/**
+ * @define {number} Zoom duration.
+ */
+ol.interaction.KEYBOARD_ZOOM_DURATION = 100;
+
+
/**
* @constructor
@@ -31,10 +37,11 @@ ol.interaction.KeyboardZoom.prototype.handleMapBrowserEvent =
if (charCode == '+'.charCodeAt(0) || charCode == '-'.charCodeAt(0)) {
var map = mapBrowserEvent.map;
var delta = (charCode == '+'.charCodeAt(0)) ? 4 : -4;
+ map.requestRenderFrame();
// FIXME works for View2D only
var view = map.getView();
goog.asserts.assert(view instanceof ol.View2D);
- view.zoom(map, delta);
+ view.zoom(map, delta, undefined, ol.interaction.KEYBOARD_ZOOM_DURATION);
keyEvent.preventDefault();
mapBrowserEvent.preventDefault();
}
View
4 src/ol/map.exports
@@ -3,7 +3,9 @@
@exportProperty ol.Map.prototype.getInteractions
@exportSymbol ol.RendererHint
+@exportProperty ol.RendererHint.CANVAS
@exportProperty ol.RendererHint.DOM
@exportProperty ol.RendererHint.WEBGL
-
+@exportSymbol ol.RendererHints
+@exportProperty ol.RendererHints.createFromQueryData
View
25 src/ol/map.js
@@ -54,6 +54,8 @@ goog.require('ol.interaction.MouseWheelZoom');
goog.require('ol.interaction.condition');
goog.require('ol.renderer.Layer');
goog.require('ol.renderer.Map');
+goog.require('ol.renderer.canvas');
+goog.require('ol.renderer.canvas.Map');
goog.require('ol.renderer.dom');
goog.require('ol.renderer.dom.Map');
goog.require('ol.renderer.webgl');
@@ -61,6 +63,12 @@ goog.require('ol.renderer.webgl.Map');
/**
+ * @define {boolean} Whether to enable canvas.
+ */
+ol.ENABLE_CANVAS = true;
+
+
+/**
* @define {boolean} Whether to enable DOM.
*/
ol.ENABLE_DOM = true;
@@ -76,6 +84,7 @@ ol.ENABLE_WEBGL = true;
* @enum {string}
*/
ol.RendererHint = {
+ CANVAS: 'canvas',
DOM: 'dom',
WEBGL: 'webgl'
};
@@ -86,6 +95,7 @@ ol.RendererHint = {
*/
ol.DEFAULT_RENDERER_HINTS = [
ol.RendererHint.WEBGL,
+ ol.RendererHint.CANVAS,
ol.RendererHint.DOM
];
@@ -608,7 +618,7 @@ ol.Map.prototype.renderFrame_ = function(time) {
frameState = {
animate: false,
backgroundColor: goog.isDef(backgroundColor) ?
- backgroundColor : new ol.Color(1, 1, 1, 1),
+ backgroundColor : new ol.Color(255, 255, 255, 1),
coordinateToPixelMatrix: this.coordinateToPixelMatrix_,
extent: null,
layersArray: layersArray,
@@ -617,6 +627,7 @@ ol.Map.prototype.renderFrame_ = function(time) {
postRenderFunctions: [],
size: size,
tileQueue: this.tileQueue_,
+ tileUsage: {},
view2DState: view2DState,
viewHints: viewHints,
time: time
@@ -794,7 +805,12 @@ ol.Map.createOptionsInternal = function(mapOptions) {
var i, rendererHint;
for (i = 0; i < rendererHints.length; ++i) {
rendererHint = rendererHints[i];
- if (rendererHint == ol.RendererHint.DOM) {
+ if (rendererHint == ol.RendererHint.CANVAS) {
+ if (ol.ENABLE_CANVAS && ol.renderer.canvas.isSupported()) {
+ rendererConstructor = ol.renderer.canvas.Map;
+ break;
+ }
+ } else if (rendererHint == ol.RendererHint.DOM) {
if (ol.ENABLE_DOM && ol.renderer.dom.isSupported()) {
rendererConstructor = ol.renderer.dom.Map;
break;
@@ -931,8 +947,9 @@ ol.Map.createInteractions_ = function(mapOptions) {
* @return {Array.<ol.RendererHint>} Renderer hints.
*/
ol.RendererHints.createFromQueryData = function(opt_queryData) {
- var queryData = goog.isDef(opt_queryData) ?
- opt_queryData : new goog.Uri.QueryData(goog.global.location.search);
+ var query = goog.global.location.search.substring(1),
+ queryData = goog.isDef(opt_queryData) ?
+ opt_queryData : new goog.Uri.QueryData(query);
if (queryData.containsKey('renderers')) {
return queryData.get('renderers').split(',');
} else if (queryData.containsKey('renderer')) {
View
11 src/ol/rectangle.js
@@ -42,6 +42,17 @@ ol.Rectangle = function(minX, minY, maxX, maxY) {
/**
+ * @param {ol.Rectangle} rectangle Rectangle.
+ */
+ol.Rectangle.prototype.extend = function(rectangle) {
+ this.minX = Math.min(this.minX, rectangle.minX);
+ this.minY = Math.min(this.minY, rectangle.minY);
+ this.maxX = Math.max(this.maxX, rectangle.maxX);
+ this.maxY = Math.max(this.maxY, rectangle.maxY);
+};
+
+
+/**
* @return {ol.Coordinate} Center.
*/
ol.Rectangle.prototype.getCenter = function() {
View
37 src/ol/renderer/canvas/canvaslayerrenderer.js
@@ -0,0 +1,37 @@
+goog.provide('ol.renderer.canvas.Layer');
+
+goog.require('ol.FrameState');
+goog.require('ol.layer.LayerState');
+goog.require('ol.renderer.Layer');
+
+
+
+/**
+ * @constructor
+ * @extends {ol.renderer.Layer}
+ * @param {ol.renderer.Map} mapRenderer Map renderer.
+ * @param {ol.layer.Layer} layer Layer.
+ */
+ol.renderer.canvas.Layer = function(mapRenderer, layer) {
+ goog.base(this, mapRenderer, layer);
+};
+goog.inherits(ol.renderer.canvas.Layer, ol.renderer.Layer);
+
+
+/**
+ * @return {HTMLCanvasElement|HTMLVideoElement|Image} Canvas.
+ */
+ol.renderer.canvas.Layer.prototype.getImage = goog.abstractMethod;
+
+
+/**
+ * @return {!goog.vec.Mat4.Number} Transform.
+ */
+ol.renderer.canvas.Layer.prototype.getTransform = goog.abstractMethod;
+
+
+/**
+ * @param {ol.FrameState} frameState Frame state.
+ * @param {ol.layer.LayerState} layerState Layer state.
+ */
+ol.renderer.canvas.Layer.prototype.renderFrame = goog.abstractMethod;
View
177 src/ol/renderer/canvas/canvasmaprenderer.js
@@ -0,0 +1,177 @@
+// FIXME offset panning
+
+goog.provide('ol.renderer.canvas.Map');
+
+goog.require('goog.dom');
+goog.require('goog.style');
+goog.require('goog.vec.Mat4');
+goog.require('ol.Size');
+goog.require('ol.layer.TileLayer');
+goog.require('ol.renderer.Map');
+goog.require('ol.renderer.canvas.TileLayer');
+
+
+
+/**
+ * @constructor
+ * @extends {ol.renderer.Map}
+ * @param {Element} container Container.
+ * @param {ol.Map} map Map.
+ */
+ol.renderer.canvas.Map = function(container, map) {
+
+ goog.base(this, container, map);
+
+ /**
+ * @private
+ * @type {ol.Size}
+ */
+ this.canvasSize_ = new ol.Size(container.clientHeight, container.clientWidth);
+
+ /**
+ * @private
+ * @type {Element}
+ */
+ this.canvas_ = goog.dom.createElement(goog.dom.TagName.CANVAS);
+ this.canvas_.height = this.canvasSize_.height;
+ this.canvas_.width = this.canvasSize_.width;
+ this.canvas_.className = 'ol-unselectable';
+ goog.dom.insertChildAt(container, this.canvas_, 0);
+
+ /**
+ * @private
+ * @type {boolean}
+ */
+ this.renderedVisible_ = true;
+
+ /**
+ * @private
+ * @type {CanvasRenderingContext2D}
+ */
+ this.context_ = this.canvas_.getContext('2d');
+
+};
+goog.inherits(ol.renderer.canvas.Map, ol.renderer.Map);
+
+
+/**
+ * @inheritDoc
+ */
+ol.renderer.canvas.Map.prototype.createLayerRenderer = function(layer) {
+ if (layer instanceof ol.layer.TileLayer) {
+ return new ol.renderer.canvas.TileLayer(this, layer);
+ } else {
+ goog.asserts.assert(false);
+ return null;
+ }
+};
+
+
+/**
+ * @inheritDoc
+ */
+ol.renderer.canvas.Map.prototype.handleBackgroundColorChanged = function() {
+ this.getMap().render();
+};
+
+
+/**
+ * @inheritDoc
+ */
+ol.renderer.canvas.Map.prototype.handleViewPropertyChanged = function() {
+ goog.base(this, 'handleViewPropertyChanged');
+ this.getMap().render();
+};
+
+
+/**
+ * @param {goog.events.Event} event Event.
+ * @protected
+ */
+ol.renderer.canvas.Map.prototype.handleLayerRendererChange = function(event) {
+ this.getMap().render();
+};
+
+
+/**
+ * @inheritDoc
+ */
+ol.renderer.canvas.Map.prototype.handleSizeChanged = function() {
+ goog.base(this, 'handleSizeChanged');
+ this.getMap().render();
+};
+
+
+/**
+ * @inheritDoc
+ */
+ol.renderer.canvas.Map.prototype.handleViewChanged = function() {
+ goog.base(this, 'handleViewChanged');
+ this.getMap().render();
+};
+
+
+/**
+ * @inheritDoc
+ */
+ol.renderer.canvas.Map.prototype.renderFrame = function(frameState) {
+
+ if (goog.isNull(frameState)) {
+ if (this.renderedVisible_) {
+ goog.style.showElement(this.canvas_, false);
+ this.renderedVisible_ = false;
+ }
+ return;
+ }
+
+ var size = frameState.size;
+ if (!this.canvasSize_.equals(size)) {
+ this.canvas_.width = size.width;
+ this.canvas_.height = size.height;
+ this.canvasSize_ = size;
+ }
+
+ var context = this.context_;
+ context.setTransform(1, 0, 0, 1, 0, 0);
+ var backgroundColor = frameState.backgroundColor;
+ context.fillStyle = 'rgb(' +
+ backgroundColor.r.toFixed(0) + ',' +
+ backgroundColor.g.toFixed(0) + ',' +
+ backgroundColor.b.toFixed(0) + ')';
+ context.globalAlpha = 1;
+ context.fillRect(0, 0, size.width, size.height);
+
+ goog.array.forEach(frameState.layersArray, function(layer) {
+
+ var layerState = frameState.layerStates[goog.getUid(layer)];
+ if (!layerState.visible) {
+ return;
+ } else if (!layerState.ready) {
+ frameState.animate = true;
+ return;
+ }
+ var layerRenderer = this.getLayerRenderer(layer);
+ layerRenderer.renderFrame(frameState, layerState);
+
+ var transform = layerRenderer.getTransform();
+ context.setTransform(
+ goog.vec.Mat4.getElement(transform, 0, 0),
+ goog.vec.Mat4.getElement(transform, 1, 0),
+ goog.vec.Mat4.getElement(transform, 0, 1),
+ goog.vec.Mat4.getElement(transform, 1, 1),
+ goog.vec.Mat4.getElement(transform, 0, 3),
+ goog.vec.Mat4.getElement(transform, 1, 3));
+
+ context.globalAlpha = layerState.opacity;
+ context.drawImage(layerRenderer.getImage(), 0, 0);
+
+ }, this);
+
+ if (!this.renderedVisible_) {
+ goog.style.showElement(this.canvas_, true);
+ this.renderedVisible_ = true;
+ }
+
+ this.calculateMatrices2D(frameState);
+
+};
View
11 src/ol/renderer/canvas/canvasrenderer.js
@@ -1,8 +1,10 @@
+goog.provide('ol.renderer.canvas');
goog.provide('ol.renderer.canvas.CanvasRenderer');
goog.require('goog.asserts');
goog.require('ol.Coordinate');
goog.require('ol.Pixel');
+goog.require('ol.canvas');
goog.require('ol.geom.Geometry');
goog.require('ol.geom.Point');
goog.require('ol.renderer.Layer');
@@ -12,6 +14,12 @@ goog.require('ol.style.LiteralStroke');
goog.require('ol.style.LiteralSymbolizer');
+/**
+ * @return {boolean} Is supported.
+ */
+ol.renderer.canvas.isSupported = ol.canvas.isSupported;
+
+
/**
* @constructor
@@ -81,7 +89,8 @@ ol.renderer.canvas.CanvasRenderer.prototype.setTarget = function(canvas) {
/**
* Render a geometry.
* @param {ol.geom.Geometry} geometry The geometry to render.
- * @param {Array.<ol.style.LiteralSymbolizer>} symbolizers Symbolizers to render with.
+ * @param {Array.<ol.style.LiteralSymbolizer>} symbolizers Symbolizers to render
+ * with.
* @private
*/
ol.renderer.canvas.CanvasRenderer.prototype.renderGeometry_ =
View
236 src/ol/renderer/canvas/canvastilelayerrenderer.js
@@ -0,0 +1,236 @@
+// FIXME don't redraw tiles if not needed
+// FIXME find correct globalCompositeOperation
+// FIXME optimize :-)
+
+goog.provide('ol.renderer.canvas.TileLayer');
+
+goog.require('goog.dom');
+goog.require('goog.style');
+goog.require('goog.vec.Mat4');
+goog.require('ol.Size');
+goog.require('ol.TileRange');
+goog.require('ol.layer.TileLayer');
+goog.require('ol.renderer.Map');
+goog.require('ol.renderer.canvas.Layer');
+
+
+
+/**
+ * @constructor
+ * @extends {ol.renderer.canvas.Layer}
+ * @param {ol.renderer.Map} mapRenderer Map renderer.
+ * @param {ol.layer.TileLayer} tileLayer Tile layer.
+ */
+ol.renderer.canvas.TileLayer = function(mapRenderer, tileLayer) {
+
+ goog.base(this, mapRenderer, tileLayer);
+
+ /**
+ * @private
+ * @type {HTMLCanvasElement}
+ */
+ this.canvas_ = null;
+
+ /**
+ * @private
+ * @type {ol.Size}
+ */
+ this.canvasSize_ = null;
+
+ /**
+ * @private
+ * @type {CanvasRenderingContext2D}
+ */
+ this.context_ = null;
+
+ /**
+ * @private
+ * @type {!goog.vec.Mat4.Number}
+ */
+ this.transform_ = goog.vec.Mat4.createNumber();
+
+};
+goog.inherits(ol.renderer.canvas.TileLayer, ol.renderer.canvas.Layer);
+
+
+/**
+ * @inheritDoc
+ */
+ol.renderer.canvas.TileLayer.prototype.getImage = function() {
+ return this.canvas_;
+};
+
+
+/**
+ * @return {ol.layer.TileLayer} Tile layer.
+ */
+ol.renderer.canvas.TileLayer.prototype.getTileLayer = function() {
+ return /** @type {ol.layer.TileLayer} */ (this.getLayer());
+};
+
+
+/**
+ * @inheritDoc
+ */
+ol.renderer.canvas.TileLayer.prototype.getTransform = function() {
+ return this.transform_;
+};
+
+
+/**
+ * @inheritDoc
+ */
+ol.renderer.canvas.TileLayer.prototype.renderFrame =
+ function(frameState, layerState) {
+
+ var view2DState = frameState.view2DState;
+
+ var tileLayer = this.getTileLayer();
+ var tileSource = tileLayer.getTileSource();
+ var tileGrid = tileSource.getTileGrid();
+ var tileSize = tileGrid.getTileSize();
+ var z = tileGrid.getZForResolution(view2DState.resolution);
+ var tileResolution = tileGrid.getResolution(z);
+ var tileRange = tileGrid.getTileRangeForExtentAndResolution(
+ frameState.extent, tileResolution);
+
+ var canvasSize = new ol.Size(
+ tileSize.width * tileRange.getWidth(),
+ tileSize.height * tileRange.getHeight());
+
+ var canvas, context;
+ if (goog.isNull(this.canvas_)) {
+ canvas = /** @type {HTMLCanvasElement} */
+ (goog.dom.createElement(goog.dom.TagName.CANVAS));
+ canvas.width = canvasSize.width;
+ canvas.height = canvasSize.height;
+ context = /** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d'));
+ this.canvas_ = canvas;
+ this.canvasSize_ = canvasSize;
+ this.context_ = context;
+ } else {
+ canvas = this.canvas_;
+ context = this.context_;
+ if (!this.canvasSize_.equals(canvasSize)) {
+ canvas.width = canvasSize.width;
+ canvas.height = canvasSize.height;
+ this.canvasSize_ = canvasSize;
+ }
+ }
+
+ context.clearRect(0, 0, canvasSize.width, canvasSize.height);
+
+ /**
+ * @type {Object.<number, Object.<string, ol.Tile>>}
+ */
+ var tilesToDrawByZ = {};
+ tilesToDrawByZ[z] = {};
+
+ var findInterimTiles = function(z, tileRange) {
+ // FIXME this could be more efficient about filling partial holes
+ var fullyCovered = true;
+ var tile, tileCoord, tileCoordKey, x, y;
+ for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
+ for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
+ tileCoord = new ol.TileCoord(z, x, y);
+ tileCoordKey = tileCoord.toString();
+ if (tilesToDrawByZ[z] && tilesToDrawByZ[z][tileCoordKey]) {
+ return;
+ }
+ tile = tileSource.getTile(tileCoord);
+ if (!goog.isNull(tile) && tile.getState() == ol.TileState.LOADED) {
+ if (!tilesToDrawByZ[z]) {
+ tilesToDrawByZ[z] = {};
+ }
+ tilesToDrawByZ[z][tileCoordKey] = tile;
+ } else {
+ fullyCovered = false;
+ }
+ }
+ }
+ return fullyCovered;
+ };
+
+ var allTilesLoaded = true;
+ var tile, tileCenter, tileCoord, tileState, x, y;
+ for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
+ for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
+
+ tileCoord = new ol.TileCoord(z, x, y);
+ tile = tileSource.getTile(tileCoord);
+ if (goog.isNull(tile)) {
+ continue;
+ }
+
+ tileState = tile.getState();
+ if (tileState == ol.TileState.IDLE) {
+ tileCenter = tileGrid.getTileCoordCenter(tileCoord);
+ frameState.tileQueue.enqueue(tile, tileCenter, tileResolution);
+ } else if (tileState == ol.TileState.LOADED) {
+ tilesToDrawByZ[z][tileCoord.toString()] = tile;
+ continue;
+ } else if (tileState == ol.TileState.ERROR) {
+ continue;
+ }
+
+ allTilesLoaded = false;
+ tileGrid.forEachTileCoordParentTileRange(tileCoord, findInterimTiles);
+
+ }
+ }
+
+ /** @type {Array.<number>} */
+ var zs = goog.array.map(goog.object.getKeys(tilesToDrawByZ), Number);
+ goog.array.sort(zs);
+ var origin = tileGrid.getTileCoordExtent(
+ new ol.TileCoord(z, tileRange.minX, tileRange.maxY)).getTopLeft();
+ var currentZ, i, scale, tileCoordKey, tileExtent, tilesToDraw;
+ for (i = 0; i < zs.length; ++i) {
+ currentZ = zs[i];
+ tilesToDraw = tilesToDrawByZ[currentZ];
+ if (currentZ == z) {
+ for (tileCoordKey in tilesToDraw) {
+ tile = tilesToDraw[tileCoordKey];
+ context.drawImage(
+ tile.getImage(),
+ tileSize.width * (tile.tileCoord.x - tileRange.minX),
+ tileSize.height * (tileRange.maxY - tile.tileCoord.y));
+ }
+ } else {
+ scale = tileGrid.getResolution(currentZ) / tileResolution;
+ for (tileCoordKey in tilesToDraw) {
+ tile = tilesToDraw[tileCoordKey];
+ tileExtent = tileGrid.getTileCoordExtent(tile.tileCoord);
+ context.drawImage(
+ tile.getImage(),
+ (tileExtent.minX - origin.x) / tileResolution,
+ (origin.y - tileExtent.maxY) / tileResolution,
+ scale * tileSize.width,
+ scale * tileSize.height);
+ }
+ }
+ }
+
+ if (!allTilesLoaded) {
+ frameState.animate = true;
+ }
+
+ this.updateTileUsage(frameState.tileUsage, tileSource, z, tileRange);
+
+ var transform = this.transform_;
+ goog.vec.Mat4.makeIdentity(transform);
+ goog.vec.Mat4.translate(transform,
+ frameState.size.width / 2, frameState.size.height / 2, 0);
+ goog.vec.Mat4.rotateZ(transform, view2DState.rotation);
+ goog.vec.Mat4.scale(
+ transform,
+ tileResolution / view2DState.resolution,
+ tileResolution / view2DState.resolution,
+ 1);
+ goog.vec.Mat4.translate(
+ transform,
+ (origin.x - view2DState.center.x) / tileResolution,
+ (view2DState.center.y - origin.y) / tileResolution,
+ 0);
+
+};
View
9 src/ol/renderer/dom/domlayerrenderer.js
@@ -30,6 +30,15 @@ goog.inherits(ol.renderer.dom.Layer, ol.renderer.Layer);
/**
+ * @inheritDoc
+ */
+ol.renderer.dom.Layer.prototype.disposeInternal = function() {
+ goog.dom.removeNode(this.target);
+ goog.base(this, 'disposeInternal');
+};
+
+
+/**
* @return {!Element} Target.
*/
ol.renderer.dom.Layer.prototype.getTarget = function() {
View
9 src/ol/renderer/dom/dommaprenderer.js
@@ -74,15 +74,6 @@ ol.renderer.dom.Map.prototype.createLayerRenderer = function(layer) {
/**
* @inheritDoc
*/
-ol.renderer.dom.Map.prototype.removeLayer = function(layer) {
- goog.base(this, 'removeLayer', layer);
- this.getMap().render();
-};
-
-
-/**
- * @inheritDoc
- */
ol.renderer.dom.Map.prototype.renderFrame = function(frameState) {
if (goog.isNull(frameState)) {
View
2  src/ol/renderer/dom/domtilelayerrenderer.js
@@ -236,6 +236,8 @@ ol.renderer.dom.TileLayer.prototype.renderFrame =
frameState.animate = true;
}
+ this.updateTileUsage(frameState.tileUsage, tileSource, z, tileRange);
+
};
View
26 src/ol/renderer/layerrenderer.js
@@ -3,6 +3,7 @@ goog.provide('ol.renderer.Layer');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('ol.Object');
+goog.require('ol.TileRange');
goog.require('ol.layer.Layer');
goog.require('ol.layer.LayerProperty');
@@ -125,3 +126,28 @@ ol.renderer.Layer.prototype.handleLayerSaturationChange = goog.nullFunction;
* @protected
*/
ol.renderer.Layer.prototype.handleLayerVisibleChange = goog.nullFunction;
+
+
+/**
+ * @protected
+ * @param {Object.<string, Object.<string, ol.TileRange>>} tileUsage Tile usage.
+ * @param {ol.source.Source} source Source.
+ * @param {number} z Z.
+ * @param {ol.TileRange} tileRange Tile range.
+ */
+ol.renderer.Layer.prototype.updateTileUsage =
+ function(tileUsage, source, z, tileRange) {
+ // FIXME should we use tilesToDrawByZ instead?
+ var sourceKey = goog.getUid(source).toString();
+ var zKey = z.toString();
+ if (sourceKey in tileUsage) {
+ if (z in tileUsage[sourceKey]) {
+ tileUsage[sourceKey][zKey].extend(tileRange);
+ } else {
+ tileUsage[sourceKey][zKey] = tileRange;
+ }
+ } else {
+ tileUsage[sourceKey] = {};
+ tileUsage[sourceKey][zKey] = tileRange;
+ }
+};
View
3  src/ol/renderer/webgl/webglmaprenderer.js
@@ -490,7 +490,8 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
gl.bindFramebuffer(goog.webgl.FRAMEBUFFER, null);
var clearColor = frameState.backgroundColor;
- gl.clearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
+ gl.clearColor(clearColor.r / 255, clearColor.g / 255,
+ clearColor.b / 255, clearColor.a);
gl.clear(goog.webgl.COLOR_BUFFER_BIT);
gl.enable(goog.webgl.BLEND);
gl.viewport(0, 0, size.width, size.height);
View
3  src/ol/renderer/webgl/webgltilelayerrenderer.js
@@ -277,7 +277,6 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame =
frameState.extent, tileResolution);
var framebufferExtent;
-
if (!goog.isNull(this.renderedTileRange_) &&
this.renderedTileRange_.equals(tileRange)) {
framebufferExtent = this.renderedFramebufferExtent_;
@@ -460,6 +459,8 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame =
}
+ this.updateTileUsage(frameState.tileUsage, tileSource, z, tileRange);
+
goog.vec.Mat4.makeIdentity(this.matrix_);
goog.vec.Mat4.translate(this.matrix_,
(view2DState.center.x - framebufferExtent.minX) /
View
28 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.<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
19 src/ol/source/stamen.exports
@@ -1,2 +1,21 @@
@exportSymbol ol.source.Stamen
+@exportSymbol ol.source.StamenFlavor
+@exportProperty ol.source.StamenFlavor.TERRAIN_BACKGROUND
+@exportProperty ol.source.StamenFlavor.TERRAIN_LABELS
+@exportProperty ol.source.StamenFlavor.TERRAIN_LINES
+@exportProperty ol.source.StamenFlavor.TONER_2010
+@exportProperty ol.source.StamenFlavor.TONER_2011
+@exportProperty ol.source.StamenFlavor.TONER_2011_LABELS
+@exportProperty ol.source.StamenFlavor.TONER_2011_LINES
+@exportProperty ol.source.StamenFlavor.TONER_2011_LITE
+@exportProperty ol.source.StamenFlavor.TONER_BACKGROUND
+@exportProperty ol.source.StamenFlavor.TONER_HYBRID
+@exportProperty ol.source.StamenFlavor.TONER_LABELS
+@exportProperty ol.source.StamenFlavor.TONER_LINES
+@exportProperty ol.source.StamenFlavor.TONER_LITE
+
+@exportSymbol ol.source.StamenProvider
+@exportProperty ol.source.StamenProvider.TERRAIN
+@exportProperty ol.source.StamenProvider.TONER
+@exportProperty ol.source.StamenProvider.WATERCOLOR
View
12 src/ol/source/stamensource.js
@@ -1,6 +1,8 @@
// FIXME Configure minZoom when supported by TileGrid
goog.provide('ol.source.Stamen');
+goog.provide('ol.source.StamenFlavor');
+goog.provide('ol.source.StamenProvider');
goog.require('ol.source.XYZ');
@@ -26,13 +28,6 @@ ol.source.StamenFlavor = {
/**
- * @typedef {{flavor: (ol.source.StamenFlavor|undefined),
- * provider: ol.source.StamenProvider}}
- */
-ol.source.StamenOptions;
-
-
-/**
* @enum {string}
*/
ol.source.StamenProvider = {
@@ -43,8 +38,7 @@ ol.source.StamenProvider = {
/**
- * @type {Object.<ol.source.StamenProvider,
- * {type: string, minZoom: number, maxZoom: number}>}
+ * @type {Object.<string, {type: string, minZoom: number, maxZoom: number}>}
*/
ol.source.StamenProviderConfig = {};
ol.source.StamenProviderConfig[ol.source.StamenProvider.TERRAIN] = {
View
28 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.<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
69 src/ol/tilecoveragearea.js
@@ -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_);
-};
View
1  src/ol/tilegrid/tilegrid.exports
@@ -0,0 +1 @@
+@exportClass ol.tilegrid.TileGrid ol.tilegrid.TileGridOptions
View
24 src/ol/tilegrid/tilegrid.js
@@ -1,7 +1,6 @@
// FIXME cope with tile grids whose minium zoom is not zero
goog.provide('ol.tilegrid.TileGrid');
-goog.provide('ol.tilegrid.TileGridOptions');
goog.require('goog.array');
goog.require('goog.asserts');
@@ -15,13 +14,9 @@ goog.require('ol.array');
/**
- * @typedef {{extent: (ol.Extent|undefined),
- * origin: (ol.Coordinate|undefined),
- * origins: (Array.<ol.Coordinate>|undefined),
- * resolutions: !Array.<number>,
- * tileSize: (ol.Size|undefined)}}
+ * @define {number} Default tile size.
*/
-ol.tilegrid.TileGridOptions;
+ol.DEFAULT_TILE_SIZE = 256;
@@ -75,7 +70,8 @@ ol.tilegrid.TileGrid = function(tileGridOptions) {
* @type {ol.Size}
*/
this.tileSize_ = goog.isDef(tileGridOptions.tileSize) ?
- tileGridOptions.tileSize : new ol.Size(256, 256);
+ tileGridOptions.tileSize :
+ new ol.Size(ol.DEFAULT_TILE_SIZE, ol.DEFAULT_TILE_SIZE);
};
@@ -321,21 +317,27 @@ ol.tilegrid.TileGrid.prototype.getZForResolution = function(resolution) {
/**
* @param {ol.Projection} projection Projection.
* @param {number=} opt_maxZoom Maximum zoom level (optional). Default is 18.
+ * @param {ol.Size=} opt_tileSize Tile size.
* @return {ol.tilegrid.TileGrid} TileGrid instance.
*/
-ol.tilegrid.createForProjection = function(projection, opt_maxZoom) {
+ol.tilegrid.createForProjection =
+ function(projection, opt_maxZoom, opt_tileSize) {
var projectionExtent = projection.getExtent();
var size = Math.max(
projectionExtent.maxX - projectionExtent.minX,
projectionExtent.maxY - projectionExtent.minY);
var maxZoom = goog.isDef(opt_maxZoom) ?
opt_maxZoom : 18;
+ var tileSize = goog.isDef(opt_tileSize) ?
+ opt_tileSize : new ol.Size(ol.DEFAULT_TILE_SIZE, ol.DEFAULT_TILE_SIZE);
var resolutions = new Array(maxZoom + 1);
+ goog.asserts.assert(tileSize.width == tileSize.height);
for (var z = 0, zz = resolutions.length; z < zz; ++z) {
- resolutions[z] = size / (256 << z);
+ resolutions[z] = size / (tileSize.width << z);
}
return new ol.tilegrid.TileGrid({
origin: projectionExtent.getTopLeft(),
- resolutions: resolutions
+ resolutions: resolutions,
+ tileSize: tileSize
});
};
View
1  src/ol/tilegrid/xyztilegrid.exports
@@ -0,0 +1 @@
+@exportClass ol.tilegrid.XYZ ol.tilegrid.XYZOptions
View
12 src/ol/tilegrid/xyztilegrid.js
@@ -1,5 +1,4 @@
goog.provide('ol.tilegrid.XYZ');
-goog.provide('ol.tilegrid.XYZOptions');
goog.require('ol.Coordinate');
goog.require('ol.Projection');
@@ -8,12 +7,6 @@ goog.require('ol.TileRange');
goog.require('ol.tilegrid.TileGrid');
-/**
- * @typedef {{maxZoom: number}}
- */
-ol.tilegrid.XYZOptions;
-
-
/**
* @constructor
@@ -25,7 +18,8 @@ ol.tilegrid.XYZ = function(xyzOptions) {
var resolutions = new Array(xyzOptions.maxZoom + 1);
var z;
for (z = 0; z <= xyzOptions.maxZoom; ++z) {
- resolutions[z] = ol.Projection.EPSG_3857_HALF_SIZE / (128 << z);
+ resolutions[z] =
+ 2 * ol.Projection.EPSG_3857_HALF_SIZE / (ol.DEFAULT_TILE_SIZE << z);
}
goog.base(this, {
@@ -33,7 +27,7 @@ ol.tilegrid.XYZ = function(xyzOptions) {
origin: new ol.Coordinate(-ol.Projection.EPSG_3857_HALF_SIZE,
ol.Projection.EPSG_3857_HALF_SIZE),
resolutions: resolutions,
- tileSize: new ol.Size(256, 256)
+ tileSize: new ol.Size(ol.DEFAULT_TILE_SIZE, ol.DEFAULT_TILE_SIZE)
});
};
View
1  src/ol/view2d.exports
@@ -0,0 +1 @@
+@exportClass ol.View2D ol.View2DOptions
View
17 src/ol/view2d.js
@@ -12,6 +12,7 @@ goog.require('ol.Projection');
goog.require('ol.ResolutionConstraint');
goog.require('ol.RotationConstraint');
goog.require('ol.View');
+goog.require('ol.animation');
/**
@@ -52,7 +53,8 @@ ol.View2D = function(opt_view2DOptions) {
var size = Math.max(
projectionExtent.maxX - projectionExtent.minX,
projectionExtent.maxY - projectionExtent.minY);
- values[ol.View2DProperty.RESOLUTION] = size / (256 << view2DOptions.zoom);
+ values[ol.View2DProperty.RESOLUTION] =
+ size / (ol.DEFAULT_TILE_SIZE << view2DOptions.zoom);
}
values[ol.View2DProperty.ROTATION] = view2DOptions.rotation;
this.setValues(values);
@@ -288,9 +290,16 @@ ol.View2D.prototype.zoom_ = function(map, resolution, opt_anchor) {
* @param {ol.Map} map Map.
* @param {number} delta Delta from previous zoom level.
* @param {ol.Coordinate=} opt_anchor Anchor coordinate.
+ * @param {number=} opt_duration Duration.
*/
-ol.View2D.prototype.zoom = function(map, delta, opt_anchor) {
- var resolution = this.constraints_.resolution(this.getResolution(), delta);
+ol.View2D.prototype.zoom = function(map, delta, opt_anchor, opt_duration) {
+ var currentResolution = this.getResolution();
+ if (goog.isDef(currentResolution) && goog.isDef(opt_duration)) {
+ map.requestRenderFrame();
+ map.addPreRenderFunction(ol.animation.createZoomFrom(
+ currentResolution, opt_duration));
+ }
+ var resolution = this.constraints_.resolution(currentResolution, delta);
this.zoom_(map, resolution, opt_anchor);
};
@@ -329,7 +338,7 @@ ol.View2D.createConstraints_ = function(view2DOptions) {
view2DOptions.projection, 'EPSG:3857').getExtent();
maxResolution = Math.max(
projectionExtent.maxX - projectionExtent.minX,
- projectionExtent.maxY - projectionExtent.minY) / 256;
+ projectionExtent.maxY - projectionExtent.minY) / ol.DEFAULT_TILE_SIZE;
// number of steps we want between two data resolutions
var numSteps = 4;
numZoomLevels = 29 * numSteps;
View
1  test/ol.html
@@ -72,6 +72,7 @@
<!-- include spec files here... -->
<script type="text/javascript" src="spec/ol/array.test.js"></script>
<script type="text/javascript" src="spec/ol/collection.test.js"></script>
+ <script type="text/javascript" src="spec/ol/color.test.js"></script>
<script type="text/javascript" src="spec/ol/extent.test.js"></script>
<script type="text/javascript" src="spec/ol/map.test.js"></script>
<script type="text/javascript" src="spec/ol/object.test.js"></script>
View
71 test/spec/ol/color.test.js
@@ -0,0 +1,71 @@
+describe('ol.Color', function() {
+
+ describe('constructor', function() {
+
+ it('limits r to 0-255', function() {
+ var c;
+
+ // legit r
+ c = new ol.Color(10.5, 11, 12, 0.5);
+ expect(c.r).toBe(10.5);
+
+ // under r
+ c = new ol.Color(-10, 11, 12, 0.5);
+ expect(c.r).toBe(0);
+
+ // over r
+ c = new ol.Color(300, 11, 12, 0.5);
+ expect(c.r).toBe(255);
+ });
+
+ it('limits g to 0-255', function() {