From 5a485ea85686da73e11e850b09f73fe5fe1916ca Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Sun, 8 Jul 2012 20:57:36 -0600 Subject: [PATCH] Getting explicit about pixels and size. Eventually, well have to ask renderers for all pixel and size related stuff. And the map overlay renderer will do all pixel<->loc math. For now, we let the map do this math based on its viewport - as this is where the mouse events are handled and it is pixels relative to the viewport that are being generated. For now, the getViewportPixelForLoc and getLocForViewportPixel are now more explicitly named. --- src/ol/Map.js | 55 +++++++++++++++++++++++++--------- src/ol/Popup.js | 2 +- src/ol/control/Navigation.js | 2 +- src/ol/renderer/MapRenderer.js | 35 ---------------------- tests/Map.html | 14 ++++----- 5 files changed, 50 insertions(+), 58 deletions(-) diff --git a/src/ol/Map.js b/src/ol/Map.js index 8690522657..b524710bc8 100644 --- a/src/ol/Map.js +++ b/src/ol/Map.js @@ -87,6 +87,12 @@ ol.Map = function() { * @type {Element} */ this.viewport_ = null; + + /** + * @private + * @type {goog.math.Size} + */ + this.viewportSize_ = null; /** * @private @@ -274,32 +280,50 @@ ol.Map.prototype.getResolution = function() { /** + * TODO: We'll have to ask the map overlay renderer for this. This method will + * not work once map space is not aligned with pixel space. + * * @param {goog.math.Coordinate|{x: number, y: number}} pixel * @return {ol.Loc} */ -ol.Map.prototype.getLocForPixel = function(pixel) { - return goog.isDef(this.renderer_) ? - this.renderer_.getLocForPixel(pixel) : null; +ol.Map.prototype.getLocForViewportPixel = function(pixel) { + var size = this.getViewportSize(); + var center = this.center_; + var resolution = this.getResolution(); + var x = center.getX() + (resolution * (pixel.x - (size.width / 2))); + var y = center.getY() - (resolution * (pixel.y - (size.height / 2))); + return new ol.Loc(x, y, undefined, this.getProjection()); }; /** + * TODO: We'll have to ask the map overlay renderer for this. This method will + * not work once map space is not aligned with pixel space. + * * @param {ol.Loc} loc * @return {{x: number, y: number}} */ -ol.Map.prototype.getPixelForLoc = function(loc) { - return goog.isDef(this.renderer_) ? - this.renderer_.getPixelForLoc(loc) : null; +ol.Map.prototype.getViewportPixelForLoc = function(loc) { + var size = this.getViewportSize(); + var center = this.center_; + var resolution = this.getResolution(); + return { + x: ((loc.getX() - center.getX()) / resolution) + (size.width / 2), + y: ((center.getY() - loc.getY()) / resolution) + (size.height / 2) + }; }; /** - * @return {goog.math.Size} The currently rendered map size in pixels. + * @return {goog.math.Size} */ -ol.Map.prototype.getSize = function() { - //TODO consider caching this when we have something like updateSize - return goog.isDef(this.renderer_) ? this.renderer_.getSize() : null; +ol.Map.prototype.getViewportSize = function() { + // TODO: listen for resize and set this.viewportSize_ null + // https://github.com/openlayers/ol3/issues/2 + if (goog.isNull(this.viewportSize_)) { + this.viewportSize_ = goog.style.getSize(this.viewport_); + } + return this.viewportSize_; }; - /** * @param {ol.Loc} center Center in map projection. */ @@ -335,8 +359,8 @@ ol.Map.prototype.setZoom = function(zoom, opt_anchor) { return; } if (goog.isDef(opt_anchor)) { - var size = this.getSize(), - anchorLoc = this.getLocForPixel(opt_anchor), + var size = this.getViewportSize(), + anchorLoc = this.getLocForViewportPixel(opt_anchor), newRes = this.getResolutionForZoom(newZoom); newCenter = anchorLoc.add( (size.width/2 - opt_anchor.x) * newRes, @@ -511,10 +535,13 @@ ol.Map.prototype.getEvents = function() { }; /** + * TODO: This method will need to be reworked/revisited when renderers can + * display a map that is rotated or otherwise not aligned with pixel space. + * * @param {number} dx pixels to move in x direction * @param {number} dy pixels to move in x direction */ -ol.Map.prototype.moveByPx = function(dx, dy) { +ol.Map.prototype.moveByViewportPx = function(dx, dy) { if (!goog.isNull(this.center_) && goog.isDef(this.zoom_)) { var resolution = this.getResolutionForZoom(this.zoom_), center = new ol.Loc( diff --git a/src/ol/Popup.js b/src/ol/Popup.js index 8ec7018aee..5a5beff366 100644 --- a/src/ol/Popup.js +++ b/src/ol/Popup.js @@ -243,7 +243,7 @@ ol.Popup.prototype.setAnchorOffset_ = function() { this.pos_ = new ol.geom.Point(this.anchor_.getX(), this.anchor_.getY()); } var pos = /** @type {ol.Loc} */ (this.pos_); - var popupPosPx = this.map_.getPixelForLoc(pos); + var popupPosPx = this.map_.getViewportPixelForLoc(pos); var popupSize = goog.style.getSize(this.container_); switch(this.placement_) { diff --git a/src/ol/control/Navigation.js b/src/ol/control/Navigation.js index 8c9fbaafc9..e56a41b2f4 100644 --- a/src/ol/control/Navigation.js +++ b/src/ol/control/Navigation.js @@ -55,7 +55,7 @@ ol.control.Navigation.prototype.deactivate = function() { * @param {Object} evt */ ol.control.Navigation.prototype.moveMap = function(evt) { - this.map_.moveByPx(evt.deltaX, evt.deltaY); + this.map_.moveByViewportPx(evt.deltaX, evt.deltaY); return false; }; diff --git a/src/ol/renderer/MapRenderer.js b/src/ol/renderer/MapRenderer.js index 911d4f8891..5fc37f62b9 100644 --- a/src/ol/renderer/MapRenderer.js +++ b/src/ol/renderer/MapRenderer.js @@ -108,38 +108,3 @@ ol.renderer.MapRenderer.pickRendererType = function(preferences) { // if we didn't find any of the preferred renderers, use the first return Renderer || Candidates[0] || null; }; - -/** - * @param {goog.math.Coordinate|{x: number, y: number}} pixel - * @return {ol.Loc} - */ -ol.renderer.MapRenderer.prototype.getLocForPixel = function(pixel) { - var center = this.renderedCenter_, - resolution = this.renderedResolution_, - size = goog.style.getSize(this.container_); - return center.add( - (pixel.x - size.width/2) * resolution, - (size.height/2 - pixel.y) * resolution - ); -}; - -/** - * @param {ol.Loc} loc - * @return {{x: number, y: number}} - */ -ol.renderer.MapRenderer.prototype.getPixelForLoc = function(loc) { - var center = this.renderedCenter_, - resolution = this.renderedResolution_, - size = this.getSize(); - return { - x: (size.width*resolution/2 + loc.getX() - center.getX())/resolution, - y: (size.height*resolution/2 - loc.getY() + center.getY())/resolution - }; -}; - -/** - * @return {goog.math.Size} The currently rendered map size in pixels. - */ -ol.renderer.MapRenderer.prototype.getSize = function() { - return goog.style.getSize(this.container_); -}; diff --git a/tests/Map.html b/tests/Map.html index e09f132442..1b7c5c2e60 100644 --- a/tests/Map.html +++ b/tests/Map.html @@ -1935,12 +1935,12 @@ map.destroy(); } - function test_moveByPx(t) { + function test_moveByViewportPx(t) { t.plan(16); var moved; var Layer = OpenLayers.Class(OpenLayers.Layer, { - moveByPx: function(dx, dy) { + moveByViewportPx: function(dx, dy) { moved[this.name] = true; } }); @@ -1972,7 +1972,7 @@ // move to a valid position moved = {}; - map.moveByPx(-455, 455); + map.moveByViewportPx(-455, 455); t.eq(map.layerContainerDiv.style.left, '455px', '[valid position] layer container left correct'); t.eq(map.layerContainerDiv.style.top, '-455px', @@ -1984,7 +1984,7 @@ // move outside the max extent moved = {}; - map.moveByPx(-4500, 4500); + map.moveByViewportPx(-4500, 4500); t.eq(map.layerContainerDiv.style.left, '455px', '[outside max extent] layer container left correct'); t.eq(map.layerContainerDiv.style.top, '-455px', @@ -1996,7 +1996,7 @@ // move outside the restricted extent moved = {}; - map.moveByPx(-500, 500); + map.moveByViewportPx(-500, 500); t.eq(map.layerContainerDiv.style.left, '455px', '[outside restricted extent] layer container left correct'); t.eq(map.layerContainerDiv.style.top, '-455px', @@ -2011,7 +2011,7 @@ } // test for http://trac.osgeo.org/openlayers/ticket/3388 - function test_moveByPx_restrictedExtent(t) { + function test_moveByViewportPx_restrictedExtent(t) { t.plan(2); var map = new OpenLayers.Map({ @@ -2024,7 +2024,7 @@ map.zoomToExtent(new OpenLayers.Bounds(-11.25, 0, 11.25, 11.25)); - map.moveByPx(-10, -10); + map.moveByViewportPx(-10, -10); t.eq(map.layerContainerDiv.style.left, '10px', 'layer container left correct'); t.eq(map.layerContainerDiv.style.top, '0px', 'layer container top correct'); }