[OpenLayers-Commits] r11535 - in trunk/openlayers: lib/OpenLayers lib/OpenLayers/Layer tests

commits-20090109 at openlayers.org commits-20090109 at openlayers.org
Fri Feb 25 13:02:17 EST 2011


Author: ahocevar
Date: 2011-02-25 10:02:12 -0800 (Fri, 25 Feb 2011)
New Revision: 11535

Modified:
   trunk/openlayers/lib/OpenLayers/Layer.js
   trunk/openlayers/lib/OpenLayers/Layer/EventPane.js
   trunk/openlayers/lib/OpenLayers/Layer/Grid.js
   trunk/openlayers/lib/OpenLayers/Map.js
   trunk/openlayers/tests/Map.html
Log:
New private movePyPx method to avoid going through all the unnecessary pixel-lonlat conversions. p=elemoine,me (closes #3062)

Modified: trunk/openlayers/lib/OpenLayers/Layer/EventPane.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Layer/EventPane.js	2011-02-25 17:05:19 UTC (rev 11534)
+++ trunk/openlayers/lib/OpenLayers/Layer/EventPane.js	2011-02-25 18:02:12 UTC (rev 11535)
@@ -211,6 +211,22 @@
         OpenLayers.Layer.prototype.setZIndex.apply(this, arguments);
         this.pane.style.zIndex = parseInt(this.div.style.zIndex) + 1;
     },
+    
+    /**
+     * Method: moveByPx
+     * Move the layer based on pixel vector. To be implemented by subclasses.
+     *
+     * Parameters:
+     * dx - {Number} The x coord of the displacement vector.
+     * dy - {Number} The y coord of the displacement vector.
+     */
+    moveByPx: function(dx, dy) {
+        OpenLayers.Layer.prototype.moveByPx.apply(this, arguments);
+        
+        if (this.dragPanMapObject) {
+            this.dragPanMapObject(dx, -dy);
+        }
+    },
 
     /**
      * Method: moveTo

Modified: trunk/openlayers/lib/OpenLayers/Layer/Grid.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Layer/Grid.js	2011-02-25 17:05:19 UTC (rev 11534)
+++ trunk/openlayers/lib/OpenLayers/Layer/Grid.js	2011-02-25 18:02:12 UTC (rev 11535)
@@ -251,19 +251,37 @@
                 if (forceReTile || !tilesBounds.containsBounds(bounds, true)) {
                     this.initGriddedTiles(bounds);
                 } else {
-                    // we might have to shift our buffer tiles, schedule
-                    // that
-                    if (this.timerId != null) {
-                        window.clearTimeout(this.timerId);
-                    }
-                    this.timerId = window.setTimeout(
-                        this._moveGriddedTiles,
-                        this.tileLoadingDelay
-                    );
+                    this.scheduleMoveGriddedTiles();
                 }
             }
         }
     },
+
+    /**
+     * Method: moveByPx
+     * Move the layer based on pixel vector.
+     *
+     * Parameters:
+     * dx - {Number}
+     * dy - {Number}
+     */
+    moveByPx: function(dx, dy) {
+        this.scheduleMoveGriddedTiles();
+    },
+
+    /**
+     * Method: scheduleMoveGriddedTiles
+     * Schedule the move of tiles.
+     */
+    scheduleMoveGriddedTiles: function() {
+        if (this.timerId != null) {
+            window.clearTimeout(this.timerId);
+        }
+        this.timerId = window.setTimeout(
+            this._moveGriddedTiles,
+            this.tileLoadingDelay
+        );
+    },
     
     /**
      * APIMethod: setTileSize
@@ -682,7 +700,9 @@
         var shifted = true;
         var buffer = this.buffer || 1;
         var tlLayer = this.grid[0][0].position;
-        var tlViewPort = this.map.getViewPortPxFromLayerPx(tlLayer);
+        var offsetX = parseInt(this.map.layerContainerDiv.style.left);
+        var offsetY = parseInt(this.map.layerContainerDiv.style.top);
+        tlViewPort = tlLayer.add(offsetX, offsetY);
         if (tlViewPort.x > -this.tileSize.w * (buffer - 1)) {
             this.shiftColumn(true);
         } else if (tlViewPort.x < -this.tileSize.w * buffer) {

Modified: trunk/openlayers/lib/OpenLayers/Layer.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Layer.js	2011-02-25 17:05:19 UTC (rev 11534)
+++ trunk/openlayers/lib/OpenLayers/Layer.js	2011-02-25 18:02:12 UTC (rev 11535)
@@ -570,6 +570,17 @@
     },
 
     /**
+     * Method: moveByPx
+     * Move the layer based on pixel vector. To be implemented by subclasses.
+     *
+     * Parameters:
+     * dx - {Number} The x coord of the displacement vector.
+     * dy - {Number} The y coord of the displacement vector.
+     */
+    moveByPx: function(dx, dy) {
+    },
+
+    /**
      * Method: setMap
      * Set the map property for the layer. This is done through an accessor
      *     so that subclasses can override this and take special action once 
@@ -1201,22 +1212,17 @@
      */
     getLonLatFromViewPortPx: function (viewPortPx) {
         var lonlat = null;
-        if (viewPortPx != null) {
-            var size = this.map.getSize();
-            var center = this.map.getCenter();
-            if (center) {
-                var res  = this.map.getResolution();
-        
-                var delta_x = viewPortPx.x - (size.w / 2);
-                var delta_y = viewPortPx.y - (size.h / 2);
-            
-                lonlat = new OpenLayers.LonLat(center.lon + delta_x * res ,
-                                             center.lat - delta_y * res); 
+        var map = this.map;
+        if (viewPortPx != null && map.minPx) {
+            var res = map.getResolution();
+            var maxExtent = map.getMaxExtent();
+            var lon = (viewPortPx.x - map.minPx.x) * res + maxExtent.left;
+            var lat = (map.minPx.y - viewPortPx.y) * res + maxExtent.top;
+            lonlat = new OpenLayers.LonLat(lon, lat);
 
-                if (this.wrapDateLine) {
-                    lonlat = lonlat.wrapDateLine(this.maxExtent);
-                }
-            } // else { DEBUG STATEMENT }
+            if (this.wrapDateLine) {
+                lonlat = lonlat.wrapDateLine(this.maxExtent);
+            }
         }
         return lonlat;
     },

Modified: trunk/openlayers/lib/OpenLayers/Map.js
===================================================================
--- trunk/openlayers/lib/OpenLayers/Map.js	2011-02-25 17:05:19 UTC (rev 11534)
+++ trunk/openlayers/lib/OpenLayers/Map.js	2011-02-25 18:02:12 UTC (rev 11535)
@@ -416,6 +416,23 @@
     paddingForPopups : null,
     
     /**
+     * Property: minPx
+     * {<OpenLayers.Pixel>} Lower left of maxExtent in viewport pixel space.
+     *     Used to verify in moveByPx that the new location we're moving to
+     *     is valid. It is also used in the getLonLatFromViewPortPx function
+     *     of Layer.
+     */
+    minPx: null,
+    
+    /**
+     * Property: maxPx
+     * {<OpenLayers.Pixel>} Top right of maxExtent in viewport pixel space.
+     *     Used to verify in moveByPx that the new location we're moving to
+     *     is valid.
+     */
+    maxPx: null,
+    
+    /**
      * Constructor: OpenLayers.Map
      * Constructor for a new OpenLayers.Map instance.  There are two possible
      *     ways to call the map constructor.  See the examples below.
@@ -1140,7 +1157,7 @@
             if (OpenLayers.Util.indexOf(this.layers, newBaseLayer) != -1) {
 
                 // preserve center and scale when changing base layers
-                var center = this.getCenter();
+                var center = this.getCachedCenter();
                 var newResolution = OpenLayers.Util.getResolutionFromScale(
                     this.getScale(), newBaseLayer.units
                 );
@@ -1402,7 +1419,7 @@
                     this.layers[i].onMapResize();                
                 }
     
-                var center = this.getCenter();
+                var center = this.getCachedCenter();
     
                 if (this.baseLayer != null && center != null) {
                     var zoom = this.getZoom();
@@ -1453,7 +1470,7 @@
         var extent = null;
         
         if (center == null) {
-            center = this.getCenter();
+            center = this.getCachedCenter();
         }                
         if (resolution == null) {
             resolution = this.getResolution();
@@ -1493,12 +1510,27 @@
      */
     getCenter: function () {
         var center = null;
-        if (this.center) {
-            center = this.center.clone();
+        var cachedCenter = this.getCachedCenter();
+        if (cachedCenter) {
+            center = cachedCenter.clone();
         }
         return center;
     },
 
+    /**
+     * Method: getCachedCenter
+     *
+     * Returns:
+     * {<OpenLayers.LonLat>}
+     */
+    getCachedCenter: function() {
+        if (!this.center && this.size) {
+            this.center = this.getLonLatFromViewPortPx(
+                new OpenLayers.Pixel(this.size.w / 2, this.size.h / 2)
+            );
+        }
+        return this.center;
+    },
 
     /**
      * APIMethod: getZoom
@@ -1527,22 +1559,30 @@
             animate: true,
             dragging: false
         });
-        // getCenter
-        var centerPx = this.getViewPortPxFromLonLat(this.getCenter());
+        if (options.dragging) {
+            if (dx != 0 || dy != 0) {
+                this.moveByPx(dx, dy);
+            }
+        } else {
+            // if we don't have a center, we were using moveByPx previously
+            var forceSetCenter = !this.center;
+            
+            // getCenter
+            var centerPx = this.getViewPortPxFromLonLat(this.getCachedCenter());
 
-        // adjust
-        var newCenterPx = centerPx.add(dx, dy);
-        
-        // only call setCenter if not dragging or there has been a change
-        if (!options.dragging || !newCenterPx.equals(centerPx)) {
-            var newCenterLonLat = this.getLonLatFromViewPortPx(newCenterPx);
-            if (options.animate) {
-                this.panTo(newCenterLonLat);
-            } else {
-                this.setCenter(newCenterLonLat, null, options.dragging);
-            }    
-        }
+            // adjust
+            var newCenterPx = centerPx.add(dx, dy);
 
+            if (forceSetCenter || !newCenterPx.equals(centerPx)) {
+                var newCenterLonLat = this.getLonLatFromViewPortPx(newCenterPx);
+                if (options.animate) {
+                    this.panTo(newCenterLonLat);
+                } else {
+                    this.setCenter(newCenterLonLat, null, options.dragging);
+                }    
+            }
+        }        
+
    },
    
    /** 
@@ -1558,7 +1598,7 @@
             if (!this.panTween) {
                 this.panTween = new OpenLayers.Tween(this.panMethod);
             }
-            var center = this.getCenter();
+            var center = this.getCachedCenter();
 
             // center will not change, don't do nothing
             if (lonlat.lon == center.lon &&
@@ -1621,6 +1661,71 @@
             'caller': 'setCenter'
         });
     },
+    
+    /** 
+     * Method: moveByPx
+     * Drag the map by pixels.
+     *
+     * Parameters:
+     * dx - {Number}
+     * dy - {Number}
+     */
+    moveByPx: function(dx, dy) {
+        dx = Math.round(dx);
+        dy = Math.round(dy);
+        var hw = this.size.w / 2;
+        var hh = this.size.h / 2;
+        var x = hw + dx;
+        var y = hh + dy;
+        var valid = y <= this.maxPx.y &&
+                    y >= this.minPx.y;
+        var minX, maxX;
+        if (this.baseLayer.wrapDateLine === true) {
+            minX = this.minPx.x, maxX = this.maxPx.x;
+        } else {
+            valid = valid &&
+                    x <= this.maxPx.x &&
+                    x >= this.minPx.x;
+        }
+        if (this.restrictedExtent && valid) {
+            valid = !(this.maxPx.x - x < hw ||
+                      x - this.minPx.x < hw ||
+                      this.maxPx.y - y < hh ||
+                      y - this.minPx.y < hh);
+        }
+        if (valid) {
+            this.center = null;
+            if (dx) {
+                this.layerContainerDiv.style.left =
+                    parseInt(this.layerContainerDiv.style.left) - dx + "px";
+                this.minPx.x -= dx;
+                this.maxPx.x -= dx;
+                if (this.baseLayer.wrapDateLine === true) {
+                    if (this.maxPx.x > maxX) {
+                        this.maxPx.x -= (maxX - minX);
+                    };
+                    if (this.minPx.x < minX) {
+                        this.minPx.x += (maxX - minX);
+                    };
+                }
+            }
+            if (dy) {
+                this.layerContainerDiv.style.top =
+                    parseInt(this.layerContainerDiv.style.top) - dy + "px";
+                this.minPx.y -= dy;
+                this.maxPx.y -= dy;
+            }
+            var layer, i, len;
+            for (i=0, len=this.layers.length; i<len; ++i) {
+                layer = this.layers[i];
+                if (layer.visibility) {
+                    layer.moveByPx(dx, dy);
+                    layer.events.triggerEvent("move");
+                }
+            }
+            this.events.triggerEvent("move");
+        }
+    },
 
     /**
      * Method: moveTo
@@ -1651,14 +1756,14 @@
             this.panTween.stop();
         }    
              
-        if (!this.center && !this.isValidLonLat(lonlat)) {
+        if (!this.getCachedCenter() && !this.isValidLonLat(lonlat)) {
             lonlat = this.maxExtent.getCenterLonLat();
         }
 
         if(this.restrictedExtent != null) {
             // In 3.0, decide if we want to change interpretation of maxExtent.
             if(lonlat == null) { 
-                lonlat = this.getCenter(); 
+                lonlat = this.center; 
             }
             if(zoom == null) { 
                 zoom = this.getZoom(); 
@@ -1705,7 +1810,7 @@
             }
 
             if (centerChanged) {
-                if ((!zoomChanged) && (this.center)) { 
+                if (!zoomChanged && this.center) { 
                     // if zoom hasnt changed, just slide layerContainer
                     //  (must be done before setting this.center to new value)
                     this.centerLayerContainer(lonlat);
@@ -1713,16 +1818,28 @@
                 this.center = lonlat.clone();
             }
 
+            var res = zoomChanged ?
+                this.getResolutionForZoom(zoom) : this.getResolution();
             // (re)set the layerContainerDiv's location
-            if ((zoomChanged) || (this.layerContainerOrigin == null)) {
-                this.layerContainerOrigin = this.center.clone();
+            if (zoomChanged || this.layerContainerOrigin == null) {
+                this.layerContainerOrigin = this.getCachedCenter();
                 this.layerContainerDiv.style.left = "0px";
                 this.layerContainerDiv.style.top  = "0px";
+                var maxExtent = this.getMaxExtent({restricted: true});
+                var maxExtentCenter = maxExtent.getCenterLonLat();
+                var lonDelta = this.center.lon - maxExtentCenter.lon;
+                var latDelta = maxExtentCenter.lat - this.center.lat;
+                var extentWidth = Math.round(maxExtent.getWidth() / res);
+                var extentHeight = Math.round(maxExtent.getHeight() / res);
+                var left = (this.size.w - extentWidth) / 2 - lonDelta / res;
+                var top = (this.size.h - extentHeight) / 2 - latDelta / res;
+                this.minPx = new OpenLayers.Pixel(left, top);
+                this.maxPx = new OpenLayers.Pixel(left + extentWidth, top + extentHeight);
             }
 
             if (zoomChanged) {
                 this.zoom = zoom;
-                this.resolution = this.getResolutionForZoom(zoom);
+                this.resolution = res;
                 // zoom level has changed, increment viewRequestID.
                 this.viewRequestID++;
             }    
@@ -1804,14 +1921,23 @@
      * lonlat - {<OpenLayers.LonLat>}
      */
     centerLayerContainer: function (lonlat) {
-
         var originPx = this.getViewPortPxFromLonLat(this.layerContainerOrigin);
         var newPx = this.getViewPortPxFromLonLat(lonlat);
 
         if ((originPx != null) && (newPx != null)) {
-            this.layerContainerDiv.style.left = Math.round(originPx.x - newPx.x) + "px";
-            this.layerContainerDiv.style.top  = Math.round(originPx.y - newPx.y) + "px";
-        }
+            var oldLeft = parseInt(this.layerContainerDiv.style.left);
+            var oldTop = parseInt(this.layerContainerDiv.style.top);
+            var newLeft = Math.round(originPx.x - newPx.x);
+            var newTop = Math.round(originPx.y - newPx.y);
+            this.layerContainerDiv.style.left = newLeft + "px";
+            this.layerContainerDiv.style.top  = newTop + "px";
+            var dx = oldLeft - newLeft;
+            var dy = oldTop - newTop;
+            this.minPx.x -= dx;
+            this.maxPx.x -= dx;
+            this.minPx.y -= dy;
+            this.maxPx.y -= dy;
+        }        
     },
 
     /**
@@ -2225,7 +2351,7 @@
         var size = this.getSize();
         var w_deg = size.w * res;
         var h_deg = size.h * res;
-        var center = this.getCenter();
+        var center = this.getCachedCenter();
 
         var extent = new OpenLayers.Bounds(center.lon - w_deg / 2,
                                            center.lat - h_deg / 2,
@@ -2337,8 +2463,8 @@
      * {<OpenLayers.Size>} The geodesic size of the pixel in kilometers.
      */
     getGeodesicPixelSize: function(px) {
-        var lonlat = px ? this.getLonLatFromPixel(px) : (this.getCenter() ||
-            new OpenLayers.LonLat(0, 0));
+        var lonlat = px ? this.getLonLatFromPixel(px) : (
+            this.getCachedCenter() || new OpenLayers.LonLat(0, 0));
         var res = this.getResolution();
         var left = lonlat.add(-res / 2, 0);
         var right = lonlat.add(res / 2, 0);

Modified: trunk/openlayers/tests/Map.html
===================================================================
--- trunk/openlayers/tests/Map.html	2011-02-25 17:05:19 UTC (rev 11534)
+++ trunk/openlayers/tests/Map.html	2011-02-25 18:02:12 UTC (rev 11535)
@@ -1323,7 +1323,7 @@
         var m = {
             'baseLayer': { 'units': {} },
             'getSize': function() { return {'w': 10, 'h': 15}; },
-            'getCenter': function() { return {'lon': -5, 'lat': -25}; },
+            'getCachedCenter': function() { return {'lon': -5, 'lat': -25}; },
             'zoomToExtent': function(extent, closest) {
                 t.ok(extent.equals(g_ExpectedExtent), "extent correctly calculated for zoomToExtent()");
                 t.ok(closest == g_Closest, "closest correctly passed on to zoomToExtent()");
@@ -1701,6 +1701,41 @@
         map.destroy();
     }    
 
+    function test_moveByPx(t) {
+        t.plan(8);
+
+        var map = new OpenLayers.Map({
+            div: 'map',
+            maxExtent: new OpenLayers.Bounds(-50, -50, 50, 50),
+            restrictedExtent: new OpenLayers.Bounds(-10, -10, 10, 10),
+            layers: [
+                new OpenLayers.Layer('name', {isBaseLayer: true})
+            ]
+        });
+        map.zoomToExtent(new OpenLayers.Bounds(-1, -1, 1, 1));
+
+        // check initial state
+        t.eq(map.layerContainerDiv.style.left, '0px', 'layer container left correct');
+        t.eq(map.layerContainerDiv.style.top, '0px', 'layer container top correct');
+
+        // move to a valid position
+        map.moveByPx(-455, 455);
+        t.eq(map.layerContainerDiv.style.left, '455px', 'layer container left correct');
+        t.eq(map.layerContainerDiv.style.top, '-455px', 'layer container top correct');
+
+        // move outside the max extent
+        map.moveByPx(-4500, 4500);
+        t.eq(map.layerContainerDiv.style.left, '455px', 'layer container left correct');
+        t.eq(map.layerContainerDiv.style.top, '-455px', 'layer container top correct');
+
+        // move outside the restricted extent
+        map.moveByPx(-500, 500);
+        t.eq(map.layerContainerDiv.style.left, '455px', 'layer container left correct');
+        t.eq(map.layerContainerDiv.style.top, '-455px', 'layer container top correct');
+
+        map.destroy();
+    }
+
   </script>
 </head>
 <body>



More information about the Commits mailing list