From 69b915620d2231051c951623fbb7a63772b1de80 Mon Sep 17 00:00:00 2001 From: Marc Jansen Date: Thu, 24 Jan 2013 10:04:36 +0100 Subject: [PATCH 01/28] Add fixme/todo target to build.py. Will show a list of lines in sourcefiles that either contains the string TODO or FIXME. Example output: user@host:~/src/ol3 $ ./build.py fixme src/ol/source/xyzsource.js has 4 matches: #1 // FIXME add minZoom support #46 // FIXME use goog.nullFunction ? #59 // FIXME factor out common code #76 // FIXME we shouldn't need a typecast here src/ol/interaction/dragpaninteraction.js has 2 matches: #1 // FIXME works for View2D only #39 // FIXME works for View2D only --- build.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/build.py b/build.py index 6d2410ae59..5dca545c20 100755 --- a/build.py +++ b/build.py @@ -85,6 +85,9 @@ virtual('precommit', 'lint', 'build-all', 'test', 'build', 'build-examples', 'do virtual('build', 'build/ol.css', 'build/ol.js') +virtual('todo', 'fixme') + + @target('build/ol.css', 'build/ol.js') def build_ol_css(t): t.touch() @@ -247,6 +250,27 @@ def hostexamples(t): def test(t): t.run('%(PHANTOMJS)s', 'test/phantom-jasmine/run_jasmine_test.coffee', 'test/ol.html') +@target('fixme', phony=True) +def find_fixme(t): + regex = re.compile(".(FIXME|TODO).") + matches = dict() + totalcount = 0 + for filename in SRC: + f = open(filename, 'r') + for lineno, line in enumerate(f): + if regex.search(line): + if (filename not in matches): + matches[filename] = list() + matches[filename].append("#" + str(lineno + 1).ljust(10) + line.strip()) + totalcount += 1 + f.close() + + for filename in matches: + print " ", filename, "has", len(matches[filename]), "matches:" + for match in matches[filename]: + print " ", match + print + print "A total number of", totalcount, "TODO/FIXME was found" if __name__ == '__main__': main() From bf63ddfebe80eb47f9a5e560288cb0ed446a9a87 Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Fri, 25 Jan 2013 09:00:54 +0100 Subject: [PATCH 02/28] Test if browser supports Windows Pointer events --- src/ol/browserfeature.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ol/browserfeature.js b/src/ol/browserfeature.js index 7335f387fd..46e40e6394 100644 --- a/src/ol/browserfeature.js +++ b/src/ol/browserfeature.js @@ -15,5 +15,6 @@ ol.BrowserFeature = { * @type {boolean} True if browser supports touch events */ HAS_TOUCH: ol.ASSUME_TOUCH || - (document && 'ontouchstart' in document.documentElement) + (document && 'ontouchstart' in document.documentElement) || + !!(window.navigator.msPointerEnabled) }; From 9c794d8b002f948a521a92526562c87e77e233fc Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Fri, 25 Jan 2013 09:02:49 +0100 Subject: [PATCH 03/28] Direct all pointer events to js code (IE pointer events). see: http://msdn.microsoft.com/en-us/library/ie/hh673557(v=vs.85).aspx --- src/ol/map.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ol/map.js b/src/ol/map.js index 277ef4a172..b4bb298093 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -189,6 +189,7 @@ ol.Map = function(mapOptions) { this.viewport_.style.overflow = 'hidden'; this.viewport_.style.width = '100%'; this.viewport_.style.height = '100%'; + this.viewport_.style.msTouchAction = 'none'; goog.dom.appendChild(this.target_, this.viewport_); /** From 43fe004917ddf05e3878ebe609b6e21f4f65c8b0 Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Fri, 25 Jan 2013 17:37:04 +0100 Subject: [PATCH 04/28] Add a comment about msTouchAction css on viewport --- src/ol/map.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ol/map.js b/src/ol/map.js index b4bb298093..9f85dfee51 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -189,6 +189,7 @@ ol.Map = function(mapOptions) { this.viewport_.style.overflow = 'hidden'; this.viewport_.style.width = '100%'; this.viewport_.style.height = '100%'; + // prevent page zoom on IE >= 10 browsers this.viewport_.style.msTouchAction = 'none'; goog.dom.appendChild(this.target_, this.viewport_); From f208e99c647fb7804e88e3942f3ed56b7031d6c6 Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Fri, 25 Jan 2013 10:34:26 +0100 Subject: [PATCH 05/28] Add missing goog.events.EventType.DBLCLICK argument to unlisten --- src/ol/mapbrowserevent.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ol/mapbrowserevent.js b/src/ol/mapbrowserevent.js index 17defe5f20..6690d68e9d 100644 --- a/src/ol/mapbrowserevent.js +++ b/src/ol/mapbrowserevent.js @@ -287,7 +287,8 @@ ol.MapBrowserEventHandler.prototype.disposeInternal = function() { goog.events.EventType.MOUSEUP, this.handleUp_, false, this); goog.events.unlisten(element, - goog.events.EventType.CLICK, this.click_, false, this); + [goog.events.EventType.CLICK, goog.events.EventType.DBLCLICK], + this.click_, false, this); if (!goog.isNull(this.dragListenerKeys_)) { goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey); this.dragListenerKeys_ = null; From 01098c4d8c7d801d969c66296656b390af35ab3f Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Mon, 28 Jan 2013 10:26:09 +0100 Subject: [PATCH 06/28] Remove event listener with goog.events.unlistenByKey --- src/ol/mapbrowserevent.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/ol/mapbrowserevent.js b/src/ol/mapbrowserevent.js index 6690d68e9d..d32200fe5f 100644 --- a/src/ol/mapbrowserevent.js +++ b/src/ol/mapbrowserevent.js @@ -117,6 +117,12 @@ ol.MapBrowserEventHandler = function(map) { */ this.timestamp_ = 0; + /** + * @type {?number} + * @private + */ + this.clickListenerKey_ = null; + /** * @type {Array.} * @private @@ -131,7 +137,7 @@ ol.MapBrowserEventHandler = function(map) { var element = this.map_.getViewport(); if (!ol.BrowserFeature.HAS_TOUCH) { - goog.events.listen(element, + this.clickListenerKey_ = goog.events.listen(element, [goog.events.EventType.CLICK, goog.events.EventType.DBLCLICK], this.click_, false, this); } @@ -286,9 +292,7 @@ ol.MapBrowserEventHandler.prototype.disposeInternal = function() { goog.events.EventType.TOUCHEND : goog.events.EventType.MOUSEUP, this.handleUp_, false, this); - goog.events.unlisten(element, - [goog.events.EventType.CLICK, goog.events.EventType.DBLCLICK], - this.click_, false, this); + goog.events.unlistenByKey(this.clickListenerKey_); if (!goog.isNull(this.dragListenerKeys_)) { goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey); this.dragListenerKeys_ = null; From 9e030854b27e8278ee9f4242310bbb7ca15c28de Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Mon, 28 Jan 2013 10:31:24 +0100 Subject: [PATCH 07/28] Don't remove event listener for this.handleUp_ twice. The listener key is in this.dragListenerKeys_ --- src/ol/mapbrowserevent.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ol/mapbrowserevent.js b/src/ol/mapbrowserevent.js index d32200fe5f..aa695f810b 100644 --- a/src/ol/mapbrowserevent.js +++ b/src/ol/mapbrowserevent.js @@ -287,11 +287,6 @@ ol.MapBrowserEventHandler.prototype.disposeInternal = function() { goog.events.EventType.TOUCHSTART : goog.events.EventType.MOUSEDOWN, this.handleDown_, false, this); - goog.events.unlisten(element, - ol.BrowserFeature.HAS_TOUCH ? - goog.events.EventType.TOUCHEND : - goog.events.EventType.MOUSEUP, - this.handleUp_, false, this); goog.events.unlistenByKey(this.clickListenerKey_); if (!goog.isNull(this.dragListenerKeys_)) { goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey); From f8646394ae60a569d26b1ffd2aaf4e33a864e593 Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Mon, 28 Jan 2013 10:37:32 +0100 Subject: [PATCH 08/28] Remove event listener with goog.events.unlistenByKey --- src/ol/mapbrowserevent.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/ol/mapbrowserevent.js b/src/ol/mapbrowserevent.js index aa695f810b..cdb40d3e66 100644 --- a/src/ol/mapbrowserevent.js +++ b/src/ol/mapbrowserevent.js @@ -123,6 +123,12 @@ ol.MapBrowserEventHandler = function(map) { */ this.clickListenerKey_ = null; + /** + * @type {?number} + * @private + */ + this.downListenerKey_ = null; + /** * @type {Array.} * @private @@ -141,7 +147,7 @@ ol.MapBrowserEventHandler = function(map) { [goog.events.EventType.CLICK, goog.events.EventType.DBLCLICK], this.click_, false, this); } - goog.events.listen(element, + this.downListenerKey_ = goog.events.listen(element, ol.BrowserFeature.HAS_TOUCH ? goog.events.EventType.TOUCHSTART : goog.events.EventType.MOUSEDOWN, @@ -281,13 +287,8 @@ ol.MapBrowserEventHandler.prototype.drag_ = function(browserEvent) { * FIXME empty description for jsdoc */ ol.MapBrowserEventHandler.prototype.disposeInternal = function() { - var element = this.map_.getViewport(); - goog.events.unlisten(element, - ol.BrowserFeature.HAS_TOUCH ? - goog.events.EventType.TOUCHSTART : - goog.events.EventType.MOUSEDOWN, - this.handleDown_, false, this); goog.events.unlistenByKey(this.clickListenerKey_); + goog.events.unlistenByKey(this.downListenerKey_); if (!goog.isNull(this.dragListenerKeys_)) { goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey); this.dragListenerKeys_ = null; From 1d2551dbcb73a2243bfa7058a3c99cf6e66a7035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 22 Jan 2013 17:04:11 +0100 Subject: [PATCH 09/28] Do not draw image if image is null --- src/ol/renderer/canvas/canvasmaprenderer.js | 23 ++++++++++++--------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/ol/renderer/canvas/canvasmaprenderer.js b/src/ol/renderer/canvas/canvasmaprenderer.js index 5d9fa3741e..bd0b3dbfe3 100644 --- a/src/ol/renderer/canvas/canvasmaprenderer.js +++ b/src/ol/renderer/canvas/canvasmaprenderer.js @@ -118,17 +118,20 @@ ol.renderer.canvas.Map.prototype.renderFrame = function(frameState) { 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)); + var image = layerRenderer.getImage(); + if (!goog.isNull(image)) { + 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); + context.globalAlpha = layerState.opacity; + context.drawImage(image, 0, 0); + } }, this); From c51b2b3fefae2b7692a7b4d9c4afabd6fd1b8230 Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Mon, 28 Jan 2013 15:18:15 +0100 Subject: [PATCH 10/28] add info about install Jasmine and the precommit hook from build.py --- readme.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index ee031aafbc..62b9f9ed5e 100644 --- a/readme.md +++ b/readme.md @@ -33,7 +33,7 @@ You can turn off compilation by appending `?mode=RAW` to the URL, for example Run the plovr web server (see above), and either open the `test/ol.html` file in the browser (e.g. ), or run `./build.py test` -on the console (headless testing with PhantomJS). +on the console (headless testing with PhantomJS, make sure to install it first from http://phantomjs.org/download.html). See also the test-specific [readme](https://github.com/openlayers/ol3/tree/master/test). @@ -45,6 +45,10 @@ Then: $ ./build.py lint +## Run the precommit hook before pushing a commit: + + $ ./build.py precommit + ## Add examples The examples are located in the `examples` directory. Adding a new example From 4701d117f7e574e498aab808c179bf31c9a03721 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Thu, 24 Jan 2013 23:37:20 +0100 Subject: [PATCH 11/28] Always dispatch change events on load/opacity/visible changes --- src/ol/renderer/dom/domlayerrenderer.js | 24 --------------------- src/ol/renderer/layerrenderer.js | 12 ++++++++--- src/ol/renderer/webgl/webgllayerrenderer.js | 24 --------------------- 3 files changed, 9 insertions(+), 51 deletions(-) diff --git a/src/ol/renderer/dom/domlayerrenderer.js b/src/ol/renderer/dom/domlayerrenderer.js index 261c24948f..4c78d42ed9 100644 --- a/src/ol/renderer/dom/domlayerrenderer.js +++ b/src/ol/renderer/dom/domlayerrenderer.js @@ -46,30 +46,6 @@ ol.renderer.dom.Layer.prototype.getTarget = function() { }; -/** - * @inheritDoc - */ -ol.renderer.dom.Layer.prototype.handleLayerLoad = function() { - this.getMap().render(); -}; - - -/** - * @inheritDoc - */ -ol.renderer.dom.Layer.prototype.handleLayerOpacityChange = function() { - this.getMap().render(); -}; - - -/** - * @inheritDoc - */ -ol.renderer.dom.Layer.prototype.handleLayerVisibleChange = function() { - this.getMap().render(); -}; - - /** * @param {ol.FrameState} frameState Frame state. * @param {ol.layer.LayerState} layerState Layer state. diff --git a/src/ol/renderer/layerrenderer.js b/src/ol/renderer/layerrenderer.js index b3243519e9..32be5e99fd 100644 --- a/src/ol/renderer/layerrenderer.js +++ b/src/ol/renderer/layerrenderer.js @@ -109,13 +109,17 @@ ol.renderer.Layer.prototype.handleLayerHueChange = goog.nullFunction; /** * @protected */ -ol.renderer.Layer.prototype.handleLayerLoad = goog.nullFunction; +ol.renderer.Layer.prototype.handleLayerLoad = function() { + this.dispatchChangeEvent(); +}; /** * @protected */ -ol.renderer.Layer.prototype.handleLayerOpacityChange = goog.nullFunction; +ol.renderer.Layer.prototype.handleLayerOpacityChange = function() { + this.dispatchChangeEvent(); +}; /** @@ -127,7 +131,9 @@ ol.renderer.Layer.prototype.handleLayerSaturationChange = goog.nullFunction; /** * @protected */ -ol.renderer.Layer.prototype.handleLayerVisibleChange = goog.nullFunction; +ol.renderer.Layer.prototype.handleLayerVisibleChange = function() { + this.dispatchChangeEvent(); +}; /** diff --git a/src/ol/renderer/webgl/webgllayerrenderer.js b/src/ol/renderer/webgl/webgllayerrenderer.js index 7fce8f5256..79195f1148 100644 --- a/src/ol/renderer/webgl/webgllayerrenderer.js +++ b/src/ol/renderer/webgl/webgllayerrenderer.js @@ -140,22 +140,6 @@ ol.renderer.webgl.Layer.prototype.handleLayerHueChange = function() { }; -/** - * @inheritDoc - */ -ol.renderer.webgl.Layer.prototype.handleLayerLoad = function() { - this.dispatchChangeEvent(); -}; - - -/** - * @inheritDoc - */ -ol.renderer.webgl.Layer.prototype.handleLayerOpacityChange = function() { - this.dispatchChangeEvent(); -}; - - /** * @inheritDoc */ @@ -167,14 +151,6 @@ ol.renderer.webgl.Layer.prototype.handleLayerSaturationChange = function() { }; -/** - * @inheritDoc - */ -ol.renderer.webgl.Layer.prototype.handleLayerVisibleChange = function() { - this.dispatchChangeEvent(); -}; - - /** * Handle webglcontextlost. */ From 49734de240b91323085edc5d7d460940718f3742 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Thu, 24 Jan 2013 23:36:39 +0100 Subject: [PATCH 12/28] Promote dispatchChangeEvent from ol.renderer.webgl.Layer to ol.renderer.Layer --- src/ol/renderer/layerrenderer.js | 8 ++++++++ src/ol/renderer/webgl/webgllayerrenderer.js | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ol/renderer/layerrenderer.js b/src/ol/renderer/layerrenderer.js index 32be5e99fd..795e51988d 100644 --- a/src/ol/renderer/layerrenderer.js +++ b/src/ol/renderer/layerrenderer.js @@ -64,6 +64,14 @@ ol.renderer.Layer = function(mapRenderer, layer) { goog.inherits(ol.renderer.Layer, ol.Object); +/** + * @protected + */ +ol.renderer.Layer.prototype.dispatchChangeEvent = function() { + this.dispatchEvent(goog.events.EventType.CHANGE); +}; + + /** * @return {ol.layer.Layer} Layer. */ diff --git a/src/ol/renderer/webgl/webgllayerrenderer.js b/src/ol/renderer/webgl/webgllayerrenderer.js index 79195f1148..988d1d6ac4 100644 --- a/src/ol/renderer/webgl/webgllayerrenderer.js +++ b/src/ol/renderer/webgl/webgllayerrenderer.js @@ -66,14 +66,6 @@ ol.renderer.webgl.Layer = function(mapRenderer, layer) { goog.inherits(ol.renderer.webgl.Layer, ol.renderer.Layer); -/** - * @protected - */ -ol.renderer.webgl.Layer.prototype.dispatchChangeEvent = function() { - this.dispatchEvent(goog.events.EventType.CHANGE); -}; - - /** * @return {!goog.vec.Mat4.Float32} Color matrix. */ From 5558d6108c2aca1357da6e01ca1e1d2c04157a72 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Mon, 28 Jan 2013 19:39:54 +0100 Subject: [PATCH 13/28] Promote handleLayerRendererChange from ol.renderer.webgl.Map to ol.renderer.Map --- src/ol/renderer/maprenderer.js | 39 ++++++++++++++++----- src/ol/renderer/webgl/webglmaprenderer.js | 42 ----------------------- 2 files changed, 30 insertions(+), 51 deletions(-) diff --git a/src/ol/renderer/maprenderer.js b/src/ol/renderer/maprenderer.js index 01313a98b3..fbd45224bf 100644 --- a/src/ol/renderer/maprenderer.js +++ b/src/ol/renderer/maprenderer.js @@ -59,6 +59,12 @@ ol.renderer.Map = function(container, map) { */ this.layersListenerKeys_ = null; + /** + * @private + * @type {Object.} + */ + this.layerRendererChangeListenKeys_ = {}; + }; goog.inherits(ol.renderer.Map, goog.Disposable); @@ -140,8 +146,8 @@ ol.renderer.Map.prototype.getCanvas = goog.functions.NULL; * @return {ol.renderer.Layer} Layer renderer. */ ol.renderer.Map.prototype.getLayerRenderer = function(layer) { - var key = goog.getUid(layer); - var layerRenderer = this.layerRenderers[key]; + var layerKey = goog.getUid(layer); + var layerRenderer = this.layerRenderers[layerKey]; goog.asserts.assert(goog.isDef(layerRenderer)); return layerRenderer; }; @@ -155,6 +161,15 @@ ol.renderer.Map.prototype.getMap = function() { }; +/** + * @param {goog.events.Event} event Event. + * @protected + */ +ol.renderer.Map.prototype.handleLayerRendererChange = function(event) { + this.getMap().render(); +}; + + /** * @param {ol.CollectionEvent} collectionEvent Collection event. * @protected @@ -213,10 +228,12 @@ ol.renderer.Map.prototype.removeLayer = function(layer) { * @protected */ ol.renderer.Map.prototype.removeLayerRenderer = function(layer) { - var key = goog.getUid(layer); - if (key in this.layerRenderers) { - var layerRenderer = this.layerRenderers[key]; - delete this.layerRenderers[key]; + var layerKey = goog.getUid(layer); + if (layerKey in this.layerRenderers) { + var layerRenderer = this.layerRenderers[layerKey]; + delete this.layerRenderers[layerKey]; + goog.events.unlistenByKey(this.layerRendererChangeListenKeys_[layerKey]); + delete this.layerRendererChangeListenKeys_[layerKey]; return layerRenderer; } else { return null; @@ -237,7 +254,11 @@ ol.renderer.Map.prototype.renderFrame = goog.nullFunction; * @protected */ ol.renderer.Map.prototype.setLayerRenderer = function(layer, layerRenderer) { - var key = goog.getUid(layer); - goog.asserts.assert(!(key in this.layerRenderers)); - this.layerRenderers[key] = layerRenderer; + var layerKey = goog.getUid(layer); + goog.asserts.assert(!(layerKey in this.layerRenderers)); + this.layerRenderers[layerKey] = layerRenderer; + goog.asserts.assert(!(layerKey in this.layerRendererChangeListenKeys_)); + this.layerRendererChangeListenKeys_[layerKey] = goog.events.listen( + layerRenderer, goog.events.EventType.CHANGE, + this.handleLayerRendererChange, false, this); }; diff --git a/src/ol/renderer/webgl/webglmaprenderer.js b/src/ol/renderer/webgl/webglmaprenderer.js index 6a62129e67..6c657fb0f5 100644 --- a/src/ol/renderer/webgl/webglmaprenderer.js +++ b/src/ol/renderer/webgl/webglmaprenderer.js @@ -206,12 +206,6 @@ ol.renderer.webgl.Map = function(container, map) { */ this.vertexShader_ = ol.renderer.webgl.map.shader.Vertex.getInstance(); - /** - * @private - * @type {Object.} - */ - this.layerRendererChangeListenKeys_ = {}; - this.initializeGL_(); }; @@ -409,15 +403,6 @@ ol.renderer.webgl.Map.prototype.getShader = function(shaderObject) { }; -/** - * @param {goog.events.Event} event Event. - * @protected - */ -ol.renderer.webgl.Map.prototype.handleLayerRendererChange = function(event) { - this.getMap().render(); -}; - - /** * @param {goog.events.Event} event Event. * @protected @@ -484,20 +469,6 @@ ol.renderer.webgl.Map.prototype.removeLayer = function(layer) { }; -/** - * @inheritDoc - */ -ol.renderer.webgl.Map.prototype.removeLayerRenderer = function(layer) { - var layerRenderer = goog.base(this, 'removeLayerRenderer', layer); - if (!goog.isNull(layerRenderer)) { - var layerKey = goog.getUid(layer); - goog.events.unlistenByKey(this.layerRendererChangeListenKeys_[layerKey]); - delete this.layerRendererChangeListenKeys_[layerKey]; - } - return layerRenderer; -}; - - /** * @inheritDoc */ @@ -604,16 +575,3 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) { } }; - - -/** - * @inheritDoc - */ -ol.renderer.webgl.Map.prototype.setLayerRenderer = function( - layer, layerRenderer) { - goog.base(this, 'setLayerRenderer', layer, layerRenderer); - var layerKey = goog.getUid(layer); - this.layerRendererChangeListenKeys_[layerKey] = goog.events.listen( - layerRenderer, goog.events.EventType.CHANGE, - this.handleLayerRendererChange, false, this); -}; From 3bd1b92b056dfa06a18d80dd3fc53a094597c20e Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Mon, 28 Jan 2013 19:56:32 +0100 Subject: [PATCH 14/28] Promote renderFrame from ol.renderer.*.LayerRender to ol.renderer.LayerRenderer --- src/ol/renderer/canvas/canvaslayerrenderer.js | 9 --------- src/ol/renderer/dom/domlayerrenderer.js | 9 --------- src/ol/renderer/layerrenderer.js | 8 ++++++++ src/ol/renderer/webgl/webgllayerrenderer.js | 10 ---------- 4 files changed, 8 insertions(+), 28 deletions(-) diff --git a/src/ol/renderer/canvas/canvaslayerrenderer.js b/src/ol/renderer/canvas/canvaslayerrenderer.js index 78ed9d6665..f63048d8e3 100644 --- a/src/ol/renderer/canvas/canvaslayerrenderer.js +++ b/src/ol/renderer/canvas/canvaslayerrenderer.js @@ -1,7 +1,5 @@ goog.provide('ol.renderer.canvas.Layer'); -goog.require('ol.FrameState'); -goog.require('ol.layer.LayerState'); goog.require('ol.renderer.Layer'); @@ -28,10 +26,3 @@ 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; diff --git a/src/ol/renderer/dom/domlayerrenderer.js b/src/ol/renderer/dom/domlayerrenderer.js index 4c78d42ed9..5a39813363 100644 --- a/src/ol/renderer/dom/domlayerrenderer.js +++ b/src/ol/renderer/dom/domlayerrenderer.js @@ -1,9 +1,7 @@ goog.provide('ol.renderer.dom.Layer'); goog.require('ol.Coordinate'); -goog.require('ol.FrameState'); goog.require('ol.layer.Layer'); -goog.require('ol.layer.LayerState'); goog.require('ol.renderer.Layer'); @@ -44,10 +42,3 @@ ol.renderer.dom.Layer.prototype.disposeInternal = function() { ol.renderer.dom.Layer.prototype.getTarget = function() { return this.target; }; - - -/** - * @param {ol.FrameState} frameState Frame state. - * @param {ol.layer.LayerState} layerState Layer state. - */ -ol.renderer.dom.Layer.prototype.renderFrame = goog.abstractMethod; diff --git a/src/ol/renderer/layerrenderer.js b/src/ol/renderer/layerrenderer.js index 795e51988d..e3f2b01635 100644 --- a/src/ol/renderer/layerrenderer.js +++ b/src/ol/renderer/layerrenderer.js @@ -7,6 +7,7 @@ goog.require('ol.Object'); goog.require('ol.TileRange'); goog.require('ol.layer.Layer'); goog.require('ol.layer.LayerProperty'); +goog.require('ol.layer.LayerState'); goog.require('ol.source.TileSource'); @@ -144,6 +145,13 @@ ol.renderer.Layer.prototype.handleLayerVisibleChange = function() { }; +/** + * @param {ol.FrameState} frameState Frame state. + * @param {ol.layer.LayerState} layerState Layer state. + */ +ol.renderer.Layer.prototype.renderFrame = goog.abstractMethod; + + /** * @protected * @param {ol.FrameState} frameState Frame state. diff --git a/src/ol/renderer/webgl/webgllayerrenderer.js b/src/ol/renderer/webgl/webgllayerrenderer.js index 988d1d6ac4..3f8f3c2d17 100644 --- a/src/ol/renderer/webgl/webgllayerrenderer.js +++ b/src/ol/renderer/webgl/webgllayerrenderer.js @@ -3,9 +3,7 @@ goog.provide('ol.renderer.webgl.Layer'); goog.require('goog.vec.Mat4'); -goog.require('ol.FrameState'); goog.require('ol.layer.Layer'); -goog.require('ol.layer.LayerState'); goog.require('ol.renderer.Layer'); goog.require('ol.vec.Mat4'); @@ -149,14 +147,6 @@ ol.renderer.webgl.Layer.prototype.handleLayerSaturationChange = function() { ol.renderer.webgl.Layer.prototype.handleWebGLContextLost = goog.nullFunction; -/** - * Render. - * @param {ol.FrameState} frameState Frame state. - * @param {ol.layer.LayerState} layerState Layer state. - */ -ol.renderer.webgl.Layer.prototype.renderFrame = goog.abstractMethod; - - /** * @private */ From 8713e848211c3fb989f52ce70ba87f224509280d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 29 Jan 2013 10:24:25 +0100 Subject: [PATCH 15/28] Change class names in DOM renderer --- src/ol/renderer/dom/dommaprenderer.js | 2 +- src/ol/renderer/dom/domtilelayerrenderer.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ol/renderer/dom/dommaprenderer.js b/src/ol/renderer/dom/dommaprenderer.js index 6f9724a746..fd6bfc75b8 100644 --- a/src/ol/renderer/dom/dommaprenderer.js +++ b/src/ol/renderer/dom/dommaprenderer.js @@ -30,7 +30,7 @@ ol.renderer.dom.Map = function(container, map) { * @private */ this.layersPane_ = goog.dom.createElement(goog.dom.TagName.DIV); - this.layersPane_.className = 'ol-layers-pane ol-unselectable'; + this.layersPane_.className = 'ol-layers ol-unselectable'; var style = this.layersPane_.style; style.position = 'absolute'; style.width = '100%'; diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index 27b2b6a804..5a87a865c6 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -30,7 +30,7 @@ goog.require('ol.tilegrid.TileGrid'); ol.renderer.dom.TileLayer = function(mapRenderer, tileLayer) { var target = goog.dom.createElement(goog.dom.TagName.DIV); - target.className = 'ol-layer'; + target.className = 'ol-layer-tile'; target.style.position = 'absolute'; goog.base(this, mapRenderer, tileLayer, target); From 713828d953375dbb1d2d2d1106865d30ddee7bf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 29 Jan 2013 10:33:35 +0100 Subject: [PATCH 16/28] Change a comma to a semi-colon (thanks @bbinet) --- src/ol/map.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ol/map.js b/src/ol/map.js index 9f85dfee51..9513467325 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -291,7 +291,7 @@ ol.Map = function(mapOptions) { this.handleSizeChanged_, false, this); goog.events.listen( this, ol.Object.getChangedEventType(ol.MapProperty.BACKGROUND_COLOR), - this.handleBackgroundColorChanged_, false, this), + this.handleBackgroundColorChanged_, false, this); this.setValues(mapOptionsInternal.values); // this gives the map an initial size From c2c87a80a13df0a0f2e18bc050e82608abb0ae6a Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Mon, 28 Jan 2013 20:33:30 +0100 Subject: [PATCH 17/28] Remove duplicate CSS rule --- css/ol.css | 3 --- 1 file changed, 3 deletions(-) diff --git a/css/ol.css b/css/ol.css index 5e679f5ddc..eca80d969c 100644 --- a/css/ol.css +++ b/css/ol.css @@ -19,9 +19,6 @@ display: inline; list-style: none; } -.ol-attribution li { - display: inline; -} .ol-attribution li:not(:last-child):after { content: "\2003"; } From 2e401b43f41d76042ce26a6451059e0693786e35 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Mon, 28 Jan 2013 20:38:02 +0100 Subject: [PATCH 18/28] Make attribution control unselectable --- src/ol/control/attributioncontrol.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ol/control/attributioncontrol.js b/src/ol/control/attributioncontrol.js index 52e33effba..e8da8080b8 100644 --- a/src/ol/control/attributioncontrol.js +++ b/src/ol/control/attributioncontrol.js @@ -24,7 +24,7 @@ ol.control.Attribution = function(attributionOptions) { this.ulElement_ = goog.dom.createElement(goog.dom.TagName.UL); var element = goog.dom.createDom(goog.dom.TagName.DIV, { - 'class': 'ol-attribution' + 'class': 'ol-attribution ol-unselectable' }, this.ulElement_); goog.base(this, { From a980de783000231d995a6cd443e44515f0915fe8 Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Tue, 29 Jan 2013 11:29:27 +0100 Subject: [PATCH 19/28] Listen to all ol.MapBrowserEvent events --- src/ol/map.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/ol/map.js b/src/ol/map.js index 9513467325..46e9743e9f 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -207,13 +207,9 @@ ol.Map = function(mapOptions) { goog.dom.appendChild(this.viewport_, this.overlayContainer_); var mapBrowserEventHandler = new ol.MapBrowserEventHandler(this); - goog.events.listen(mapBrowserEventHandler, [ - ol.MapBrowserEvent.EventType.CLICK, - ol.MapBrowserEvent.EventType.DBLCLICK, - ol.MapBrowserEvent.EventType.DRAGSTART, - ol.MapBrowserEvent.EventType.DRAG, - ol.MapBrowserEvent.EventType.DRAGEND - ], this.handleMapBrowserEvent, false, this); + goog.events.listen(mapBrowserEventHandler, + goog.object.getValues(ol.MapBrowserEvent.EventType), + this.handleMapBrowserEvent, false, this); this.registerDisposable(mapBrowserEventHandler); // FIXME we probably shouldn't listen on document... From 8a9738d755d9e09eb467354df64275e5862c57c1 Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Mon, 28 Jan 2013 17:33:15 +0100 Subject: [PATCH 20/28] Add support for kinetic effect while dragging. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only dragpan interaction is supported for now. The kinetic effect use the maths below (thx @twpayne): Rate of decay (number, must be negative) = α Minimum velocity (pixels/millisecond) = v_min Initial velocity (pixels/millisecond) = v₀ Velocity at time t (pixels/millisecond) = α⋅t v₀⋅ℯ Distance travelled at time t (pixels) = ⎛ α⋅t ⎞ v₀⋅⎝ℯ - 1⎠ ───────────── α Duration of animation (milliseconds) = ⎛v_min⎞ log⎜─────⎟ ⎝ v₀ ⎠ ────────── α Total distance travelled (pixels) = -v₀ + v_min ─────────── α Easing function = ⎛ α⋅duration⋅t ⎞ v₀⋅⎝ℯ - 1⎠ ────────────────────── -v₀ + v_min --- src/ol/interaction/dragpaninteraction.js | 42 ++++++- src/ol/kinetic.js | 143 +++++++++++++++++++++++ 2 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 src/ol/kinetic.js diff --git a/src/ol/interaction/dragpaninteraction.js b/src/ol/interaction/dragpaninteraction.js index 3fcc4d4157..4598cabec1 100644 --- a/src/ol/interaction/dragpaninteraction.js +++ b/src/ol/interaction/dragpaninteraction.js @@ -7,6 +7,7 @@ goog.require('ol.Coordinate'); goog.require('ol.MapBrowserEvent'); goog.require('ol.View2D'); goog.require('ol.ViewHint'); +goog.require('ol.animation'); goog.require('ol.interaction.ConditionType'); goog.require('ol.interaction.Drag'); @@ -16,8 +17,9 @@ goog.require('ol.interaction.Drag'); * @constructor * @extends {ol.interaction.Drag} * @param {ol.interaction.ConditionType} condition Condition. + * @param {ol.Kinetic=} opt_kinetic Kinetic object. */ -ol.interaction.DragPan = function(condition) { +ol.interaction.DragPan = function(condition, opt_kinetic) { goog.base(this); @@ -27,6 +29,12 @@ ol.interaction.DragPan = function(condition) { */ this.condition_ = condition; + /** + * @private + * @type {ol.Kinetic|undefined} + */ + this.kinetic_ = opt_kinetic; + }; goog.inherits(ol.interaction.DragPan, ol.interaction.Drag); @@ -35,6 +43,9 @@ goog.inherits(ol.interaction.DragPan, ol.interaction.Drag); * @inheritDoc */ ol.interaction.DragPan.prototype.handleDrag = function(mapBrowserEvent) { + if (this.kinetic_) { + this.kinetic_.update(mapBrowserEvent.browserEvent); + } var map = mapBrowserEvent.map; // FIXME works for View2D only var view = map.getView(); @@ -55,9 +66,31 @@ ol.interaction.DragPan.prototype.handleDrag = function(mapBrowserEvent) { * @inheritDoc */ ol.interaction.DragPan.prototype.handleDragEnd = function(mapBrowserEvent) { + + // FIXME works for View2D only + var map = mapBrowserEvent.map; - map.requestRenderFrame(); - map.getView().setHint(ol.ViewHint.PANNING, -1); + var view = map.getView(); + view.setHint(ol.ViewHint.PANNING, -1); + + if (this.kinetic_ && this.kinetic_.end()) { + var distance = this.kinetic_.getDistance(); + var angle = this.kinetic_.getAngle(); + var center = view.getCenter(); + var kineticPanFrom = ol.animation.createPanFrom({ + source: center, + duration: this.kinetic_.getDuration(), + easing: this.kinetic_.getEasingFn() + }); + map.addPreRenderFunction(kineticPanFrom); + + var centerpx = map.getPixelFromCoordinate(center); + var destpx = new ol.Pixel( + centerpx.x - distance * Math.cos(angle), + centerpx.y - distance * Math.sin(angle)); + var dest = map.getCoordinateFromPixel(destpx); + view.setCenter(dest); + } }; @@ -67,6 +100,9 @@ ol.interaction.DragPan.prototype.handleDragEnd = function(mapBrowserEvent) { ol.interaction.DragPan.prototype.handleDragStart = function(mapBrowserEvent) { var browserEvent = mapBrowserEvent.browserEvent; if (this.condition_(browserEvent)) { + if (this.kinetic_) { + this.kinetic_.begin(browserEvent); + } var map = mapBrowserEvent.map; map.requestRenderFrame(); map.getView().setHint(ol.ViewHint.PANNING, 1); diff --git a/src/ol/kinetic.js b/src/ol/kinetic.js new file mode 100644 index 0000000000..909fbb4936 --- /dev/null +++ b/src/ol/kinetic.js @@ -0,0 +1,143 @@ + +goog.provide('ol.Kinetic'); + +goog.require('goog.array'); +goog.require('ol.Pixel'); + + +/** + * @typedef {{x: number, + * y: number, + * t: number}} + */ +ol.KineticPoint; + + + +/** + * @constructor + * @param {number} decay Rate of decay (must be negative). + * @param {number} v_min Minimum velocity (pixels/millisecond). + * @param {number} delay Delay to consider to calculate the kinetic + * initial values (milliseconds). + */ +ol.Kinetic = function(decay, v_min, delay) { + + /** + * @private + * @type {number} + */ + this.decay_ = decay; + + /** + * @private + * @type {number} + */ + this.v_min_ = v_min; + + /** + * @private + * @type {number} + */ + this.delay_ = delay; + + /** + * @private + * @type {Array.} + */ + this.points_ = []; + + /** + * @private + * @type {number} + */ + this.angle_ = 0; + + /** + * @private + * @type {number} + */ + this.v_0_ = 0; +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + */ +ol.Kinetic.prototype.begin = function(browserEvent) { + this.points_.length = 0; + this.angle_ = 0; + this.v_0_ = 0; + this.update(browserEvent); +}; + + +/** + * @param {goog.events.BrowserEvent} browserEvent Browser event. + */ +ol.Kinetic.prototype.update = function(browserEvent) { + this.points_.push({ + x: browserEvent.clientX, + y: browserEvent.clientY, + t: goog.now() + }); +}; + + +/** + * @return {boolean} Whether we should do kinetic animation. + */ +ol.Kinetic.prototype.end = function() { + var now = goog.now(); + var index = Math.abs(goog.array.binarySelect(this.points_, function(elt) { + return elt.t < now - this.delay_; + }, this)); + if (index < this.points_.length - 1) { + var first = this.points_[index]; + var last = this.points_[this.points_.length - 1]; + var dx = last.x - first.x; + var dy = last.y - first.y; + this.angle_ = Math.atan2(dy, dx); + this.v_0_ = Math.sqrt(dx * dx + dy * dy) / (last.t - first.t); + return this.v_0_ > this.v_min_; + } + return false; +}; + + +/** + * @return {function(number): number} Easing function for kinetic animation. + */ +ol.Kinetic.prototype.getEasingFn = function() { + var decay = this.decay_; + var v_0 = this.v_0_; + var v_min = this.v_min_; + var duration = this.getDuration(); + return function(t) { + return v_0 * (Math.exp((decay * t) * duration) - 1) / (v_min - v_0); + }; +}; + + +/** + * @return {number} Duration of animation (milliseconds). + */ +ol.Kinetic.prototype.getDuration = function() { + return Math.log(this.v_min_ / this.v_0_) / this.decay_; +}; + + +/** + * @return {number} Total distance travelled (pixels). + */ +ol.Kinetic.prototype.getDistance = function() { + return (this.v_min_ - this.v_0_) / this.decay_; +}; + + +/** + * @return {number} Angle of the kinetic panning animation (radians). + */ +ol.Kinetic.prototype.getAngle = function() { + return this.angle_; +}; From 7d0b4c757ea80379e6b719a7da2f42e84641d75d Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Mon, 28 Jan 2013 17:40:00 +0100 Subject: [PATCH 21/28] Activate kinetic effect by default --- src/ol/map.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ol/map.js b/src/ol/map.js index 46e9743e9f..1432c45612 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -29,6 +29,7 @@ goog.require('ol.Color'); goog.require('ol.Coordinate'); goog.require('ol.Extent'); goog.require('ol.FrameState'); +goog.require('ol.Kinetic'); goog.require('ol.MapBrowserEvent'); goog.require('ol.Object'); goog.require('ol.Pixel'); @@ -984,7 +985,8 @@ ol.Map.createInteractions_ = function(mapOptions) { mapOptions.dragPan : true; if (dragPan) { interactions.push( - new ol.interaction.DragPan(ol.interaction.condition.noModifierKeys)); + new ol.interaction.DragPan(ol.interaction.condition.noModifierKeys, + new ol.Kinetic(-0.005, 0.05, 100))); } var keyboard = goog.isDef(mapOptions.keyboard) ? From d54864695db8a922337f5d67e11b698bb06914b8 Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Tue, 29 Jan 2013 12:56:15 +0100 Subject: [PATCH 22/28] Add a removePreRenderFunction method to ol.Map This will remove the pre-render function from preRenderFunctions_ array if found. --- src/ol/map.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ol/map.js b/src/ol/map.js index 1432c45612..23b42bc203 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -326,6 +326,15 @@ ol.Map.prototype.addPreRenderFunctions = function(preRenderFunctions) { }; +/** + * @param {ol.PreRenderFunction} preRenderFunction Pre-render function. + * @return {boolean} Whether the preRenderFunction has been found and removed. + */ +ol.Map.prototype.removePreRenderFunction = function(preRenderFunction) { + return goog.array.remove(this.preRenderFunctions_, preRenderFunction); +}; + + /** * * @inheritDoc From 39cbba3eb7eb569c713932992b870f9093d1b6fe Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Tue, 29 Jan 2013 13:00:02 +0100 Subject: [PATCH 23/28] Add a frameState property to ol.MapBrowserEvent so that we will be able to retrieve the current center of the view2d from the framestate in the dragpan interaction. --- src/ol/map.js | 1 + src/ol/mapbrowserevent.js | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/ol/map.js b/src/ol/map.js index 23b42bc203..22609eb4a6 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -542,6 +542,7 @@ ol.Map.prototype.handleControlsRemove_ = function(collectionEvent) { * @param {ol.MapBrowserEvent} mapBrowserEvent The event to handle. */ ol.Map.prototype.handleMapBrowserEvent = function(mapBrowserEvent) { + mapBrowserEvent.frameState = this.frameState_; var interactions = this.getInteractions(); var interactionsArray = /** @type {Array.} */ (interactions.getArray()); diff --git a/src/ol/mapbrowserevent.js b/src/ol/mapbrowserevent.js index cdb40d3e66..a6b0f20be7 100644 --- a/src/ol/mapbrowserevent.js +++ b/src/ol/mapbrowserevent.js @@ -21,10 +21,11 @@ goog.require('ol.Pixel'); * @param {string} type Event type. * @param {ol.Map} map Map. * @param {goog.events.BrowserEvent} browserEvent Browser event. + * @param {?ol.FrameState=} opt_frameState Frame state. */ -ol.MapBrowserEvent = function(type, map, browserEvent) { +ol.MapBrowserEvent = function(type, map, browserEvent, opt_frameState) { - goog.base(this, type, map); + goog.base(this, type, map, opt_frameState); /** * @type {goog.events.BrowserEvent} @@ -230,6 +231,9 @@ ol.MapBrowserEventHandler.prototype.handleUp_ = function(browserEvent) { * @private */ ol.MapBrowserEventHandler.prototype.handleDown_ = function(browserEvent) { + var newEvent = new ol.MapBrowserEvent( + ol.MapBrowserEvent.EventType.DOWN, this.map_, browserEvent); + this.dispatchEvent(newEvent); if (!this.previous_) { this.touchEnableBrowserEvent_(browserEvent); this.down_ = browserEvent; @@ -306,5 +310,6 @@ ol.MapBrowserEvent.EventType = { DBLCLICK: goog.events.EventType.DBLCLICK, DRAGSTART: 'dragstart', DRAG: 'drag', - DRAGEND: 'dragend' + DRAGEND: 'dragend', + DOWN: 'down' }; From 2bb8a5cfd9abc75915f08fdbee082b81cbd0ab7d Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Tue, 29 Jan 2013 14:12:01 +0100 Subject: [PATCH 24/28] Stop current kinetic animation on DOWN events --- src/ol/interaction/draginteraction.js | 11 ++++++++++ src/ol/interaction/dragpaninteraction.js | 28 ++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/ol/interaction/draginteraction.js b/src/ol/interaction/draginteraction.js index b41e548a6b..1d525bae7d 100644 --- a/src/ol/interaction/draginteraction.js +++ b/src/ol/interaction/draginteraction.js @@ -80,6 +80,13 @@ ol.interaction.Drag.prototype.handleDragEnd = goog.nullFunction; ol.interaction.Drag.prototype.handleDragStart = goog.functions.FALSE; +/** + * @param {ol.MapBrowserEvent} mapBrowserEvent Event. + * @protected + */ +ol.interaction.Drag.prototype.handleDown = goog.nullFunction; + + /** * @inheritDoc */ @@ -91,6 +98,10 @@ ol.interaction.Drag.prototype.handleMapBrowserEvent = } var view = map.getView(); var browserEvent = mapBrowserEvent.browserEvent; + if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DOWN) { + goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent); + this.handleDown(mapBrowserEvent); + } if (this.dragging_) { if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DRAG) { goog.asserts.assert(browserEvent instanceof goog.events.BrowserEvent); diff --git a/src/ol/interaction/dragpaninteraction.js b/src/ol/interaction/dragpaninteraction.js index 4598cabec1..dcd9e752da 100644 --- a/src/ol/interaction/dragpaninteraction.js +++ b/src/ol/interaction/dragpaninteraction.js @@ -35,6 +35,12 @@ ol.interaction.DragPan = function(condition, opt_kinetic) { */ this.kinetic_ = opt_kinetic; + /** + * @private + * @type {?ol.PreRenderFunction} + */ + this.kineticPreRenderFn_ = null; + }; goog.inherits(ol.interaction.DragPan, ol.interaction.Drag); @@ -77,12 +83,12 @@ ol.interaction.DragPan.prototype.handleDragEnd = function(mapBrowserEvent) { var distance = this.kinetic_.getDistance(); var angle = this.kinetic_.getAngle(); var center = view.getCenter(); - var kineticPanFrom = ol.animation.createPanFrom({ + this.kineticPreRenderFn_ = ol.animation.createPanFrom({ source: center, duration: this.kinetic_.getDuration(), easing: this.kinetic_.getEasingFn() }); - map.addPreRenderFunction(kineticPanFrom); + map.addPreRenderFunction(this.kineticPreRenderFn_); var centerpx = map.getPixelFromCoordinate(center); var destpx = new ol.Pixel( @@ -111,3 +117,21 @@ ol.interaction.DragPan.prototype.handleDragStart = function(mapBrowserEvent) { return false; } }; + + +/** + * @inheritDoc + */ +ol.interaction.DragPan.prototype.handleDown = function(mapBrowserEvent) { + var map = mapBrowserEvent.map; + // FIXME works for View2D only + var view = map.getView(); + goog.asserts.assert(view instanceof ol.View2D); + goog.asserts.assert(!goog.isNull(mapBrowserEvent.frameState)); + if (!goog.isNull(this.kineticPreRenderFn_) && + map.removePreRenderFunction(this.kineticPreRenderFn_)) { + map.requestRenderFrame(); + view.setCenter(mapBrowserEvent.frameState.view2DState.center); + this.kineticPreRenderFn_ = null; + } +}; From 79849888db6e7492f0399102492c6318e01d38a3 Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Tue, 29 Jan 2013 14:50:12 +0100 Subject: [PATCH 25/28] Kinetic now returns directly the pre-render function instead of returning the kinetic easing function only. (thanks @fredj) --- src/ol/interaction/dragpaninteraction.js | 7 +------ src/ol/kinetic.js | 13 ++++++++++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/ol/interaction/dragpaninteraction.js b/src/ol/interaction/dragpaninteraction.js index dcd9e752da..5c516d62ff 100644 --- a/src/ol/interaction/dragpaninteraction.js +++ b/src/ol/interaction/dragpaninteraction.js @@ -7,7 +7,6 @@ goog.require('ol.Coordinate'); goog.require('ol.MapBrowserEvent'); goog.require('ol.View2D'); goog.require('ol.ViewHint'); -goog.require('ol.animation'); goog.require('ol.interaction.ConditionType'); goog.require('ol.interaction.Drag'); @@ -83,11 +82,7 @@ ol.interaction.DragPan.prototype.handleDragEnd = function(mapBrowserEvent) { var distance = this.kinetic_.getDistance(); var angle = this.kinetic_.getAngle(); var center = view.getCenter(); - this.kineticPreRenderFn_ = ol.animation.createPanFrom({ - source: center, - duration: this.kinetic_.getDuration(), - easing: this.kinetic_.getEasingFn() - }); + this.kineticPreRenderFn_ = this.kinetic_.createPanFrom(center); map.addPreRenderFunction(this.kineticPreRenderFn_); var centerpx = map.getPixelFromCoordinate(center); diff --git a/src/ol/kinetic.js b/src/ol/kinetic.js index 909fbb4936..4f952477de 100644 --- a/src/ol/kinetic.js +++ b/src/ol/kinetic.js @@ -3,6 +3,7 @@ goog.provide('ol.Kinetic'); goog.require('goog.array'); goog.require('ol.Pixel'); +goog.require('ol.animation'); /** @@ -106,16 +107,22 @@ ol.Kinetic.prototype.end = function() { /** - * @return {function(number): number} Easing function for kinetic animation. + * @param {ol.Coordinate} source Source coordinate for the animation. + * @return {ol.PreRenderFunction} Pre-render function for kinetic animation. */ -ol.Kinetic.prototype.getEasingFn = function() { +ol.Kinetic.prototype.createPanFrom = function(source) { var decay = this.decay_; var v_0 = this.v_0_; var v_min = this.v_min_; var duration = this.getDuration(); - return function(t) { + var easingFunction = function(t) { return v_0 * (Math.exp((decay * t) * duration) - 1) / (v_min - v_0); }; + return ol.animation.createPanFrom({ + source: source, + duration: duration, + easing: easingFunction + }); }; From d91e1d30d472bf4788b6099d7b2e3bdc9d586f83 Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Wed, 30 Jan 2013 11:42:53 +0100 Subject: [PATCH 26/28] Get rid of binarySelect to find the first point. --- src/ol/kinetic.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/ol/kinetic.js b/src/ol/kinetic.js index 4f952477de..875eea7a16 100644 --- a/src/ol/kinetic.js +++ b/src/ol/kinetic.js @@ -90,12 +90,14 @@ ol.Kinetic.prototype.update = function(browserEvent) { */ ol.Kinetic.prototype.end = function() { var now = goog.now(); - var index = Math.abs(goog.array.binarySelect(this.points_, function(elt) { - return elt.t < now - this.delay_; - }, this)); - if (index < this.points_.length - 1) { - var first = this.points_[index]; - var last = this.points_[this.points_.length - 1]; + var lastIndex = this.points_.length - 1; + var firstIndex = lastIndex - 1; + while (firstIndex >= 0 && this.points_[firstIndex].t > now - this.delay_) { + firstIndex--; + } + if (firstIndex >= 0) { + var first = this.points_[firstIndex]; + var last = this.points_[lastIndex]; var dx = last.x - first.x; var dy = last.y - first.y; this.angle_ = Math.atan2(dy, dx); From dff8c2b2b2b1de1e070af465c406a8e1d75e281c Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Wed, 30 Jan 2013 11:53:57 +0100 Subject: [PATCH 27/28] Renaming to be more consistent with ol3 style s/v_0/initialVelocity/ s/v_min/minVelocity/ --- src/ol/kinetic.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/ol/kinetic.js b/src/ol/kinetic.js index 875eea7a16..6f98e60d51 100644 --- a/src/ol/kinetic.js +++ b/src/ol/kinetic.js @@ -18,11 +18,11 @@ ol.KineticPoint; /** * @constructor * @param {number} decay Rate of decay (must be negative). - * @param {number} v_min Minimum velocity (pixels/millisecond). + * @param {number} minVelocity Minimum velocity (pixels/millisecond). * @param {number} delay Delay to consider to calculate the kinetic * initial values (milliseconds). */ -ol.Kinetic = function(decay, v_min, delay) { +ol.Kinetic = function(decay, minVelocity, delay) { /** * @private @@ -34,7 +34,7 @@ ol.Kinetic = function(decay, v_min, delay) { * @private * @type {number} */ - this.v_min_ = v_min; + this.minVelocity_ = minVelocity; /** * @private @@ -58,7 +58,7 @@ ol.Kinetic = function(decay, v_min, delay) { * @private * @type {number} */ - this.v_0_ = 0; + this.initialVelocity_ = 0; }; @@ -68,7 +68,7 @@ ol.Kinetic = function(decay, v_min, delay) { ol.Kinetic.prototype.begin = function(browserEvent) { this.points_.length = 0; this.angle_ = 0; - this.v_0_ = 0; + this.initialVelocity_ = 0; this.update(browserEvent); }; @@ -101,8 +101,8 @@ ol.Kinetic.prototype.end = function() { var dx = last.x - first.x; var dy = last.y - first.y; this.angle_ = Math.atan2(dy, dx); - this.v_0_ = Math.sqrt(dx * dx + dy * dy) / (last.t - first.t); - return this.v_0_ > this.v_min_; + this.initialVelocity_ = Math.sqrt(dx * dx + dy * dy) / (last.t - first.t); + return this.initialVelocity_ > this.minVelocity_; } return false; }; @@ -114,11 +114,12 @@ ol.Kinetic.prototype.end = function() { */ ol.Kinetic.prototype.createPanFrom = function(source) { var decay = this.decay_; - var v_0 = this.v_0_; - var v_min = this.v_min_; + var initialVelocity = this.initialVelocity_; + var minVelocity = this.minVelocity_; var duration = this.getDuration(); var easingFunction = function(t) { - return v_0 * (Math.exp((decay * t) * duration) - 1) / (v_min - v_0); + return initialVelocity * (Math.exp((decay * t) * duration) - 1) / + (minVelocity - initialVelocity); }; return ol.animation.createPanFrom({ source: source, @@ -132,7 +133,7 @@ ol.Kinetic.prototype.createPanFrom = function(source) { * @return {number} Duration of animation (milliseconds). */ ol.Kinetic.prototype.getDuration = function() { - return Math.log(this.v_min_ / this.v_0_) / this.decay_; + return Math.log(this.minVelocity_ / this.initialVelocity_) / this.decay_; }; @@ -140,7 +141,7 @@ ol.Kinetic.prototype.getDuration = function() { * @return {number} Total distance travelled (pixels). */ ol.Kinetic.prototype.getDistance = function() { - return (this.v_min_ - this.v_0_) / this.decay_; + return (this.minVelocity_ - this.initialVelocity_) / this.decay_; }; From d2f30986db0d460bc41c7d6bcccbd71b02c0c1ea Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Wed, 30 Jan 2013 13:39:16 +0100 Subject: [PATCH 28/28] Set kinetic getDuration instance method to @private --- src/ol/kinetic.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ol/kinetic.js b/src/ol/kinetic.js index 6f98e60d51..44aabe850b 100644 --- a/src/ol/kinetic.js +++ b/src/ol/kinetic.js @@ -116,7 +116,7 @@ ol.Kinetic.prototype.createPanFrom = function(source) { var decay = this.decay_; var initialVelocity = this.initialVelocity_; var minVelocity = this.minVelocity_; - var duration = this.getDuration(); + var duration = this.getDuration_(); var easingFunction = function(t) { return initialVelocity * (Math.exp((decay * t) * duration) - 1) / (minVelocity - initialVelocity); @@ -130,9 +130,10 @@ ol.Kinetic.prototype.createPanFrom = function(source) { /** + * @private * @return {number} Duration of animation (milliseconds). */ -ol.Kinetic.prototype.getDuration = function() { +ol.Kinetic.prototype.getDuration_ = function() { return Math.log(this.minVelocity_ / this.initialVelocity_) / this.decay_; };