New private movePyPx method to avoid going through all the unnecessary pixel-lonlat conversions. p=elemoine,me (closes #3062)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@11535 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
@@ -569,6 +569,17 @@ OpenLayers.Layer = OpenLayers.Class({
|
||||
this.display(display);
|
||||
},
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -1201,22 +1212,17 @@ OpenLayers.Layer = OpenLayers.Class({
|
||||
*/
|
||||
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 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);
|
||||
|
||||
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);
|
||||
|
||||
if (this.wrapDateLine) {
|
||||
lonlat = lonlat.wrapDateLine(this.maxExtent);
|
||||
}
|
||||
} // else { DEBUG STATEMENT }
|
||||
if (this.wrapDateLine) {
|
||||
lonlat = lonlat.wrapDateLine(this.maxExtent);
|
||||
}
|
||||
}
|
||||
return lonlat;
|
||||
},
|
||||
|
||||
@@ -212,6 +212,22 @@ OpenLayers.Layer.EventPane = OpenLayers.Class(OpenLayers.Layer, {
|
||||
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
|
||||
* Handle calls to move the layer.
|
||||
|
||||
@@ -251,20 +251,38 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
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
|
||||
* Check if we are in singleTile mode and if so, set the size as a ratio
|
||||
@@ -682,7 +700,9 @@ OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
|
||||
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) {
|
||||
|
||||
@@ -415,6 +415,23 @@ OpenLayers.Map = OpenLayers.Class({
|
||||
*/
|
||||
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
|
||||
@@ -1140,7 +1157,7 @@ OpenLayers.Map = OpenLayers.Class({
|
||||
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 @@ OpenLayers.Map = OpenLayers.Class({
|
||||
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 @@ OpenLayers.Map = OpenLayers.Class({
|
||||
var extent = null;
|
||||
|
||||
if (center == null) {
|
||||
center = this.getCenter();
|
||||
center = this.getCachedCenter();
|
||||
}
|
||||
if (resolution == null) {
|
||||
resolution = this.getResolution();
|
||||
@@ -1493,12 +1510,27 @@ OpenLayers.Map = OpenLayers.Class({
|
||||
*/
|
||||
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,19 +1559,27 @@ OpenLayers.Map = OpenLayers.Class({
|
||||
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;
|
||||
|
||||
// adjust
|
||||
var newCenterPx = centerPx.add(dx, dy);
|
||||
// getCenter
|
||||
var centerPx = this.getViewPortPxFromLonLat(this.getCachedCenter());
|
||||
|
||||
// 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 @@ OpenLayers.Map = OpenLayers.Class({
|
||||
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 &&
|
||||
@@ -1622,6 +1662,71 @@ OpenLayers.Map = OpenLayers.Class({
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 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 @@ OpenLayers.Map = OpenLayers.Class({
|
||||
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 @@ OpenLayers.Map = OpenLayers.Class({
|
||||
}
|
||||
|
||||
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 @@ OpenLayers.Map = OpenLayers.Class({
|
||||
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,13 +1921,22 @@ OpenLayers.Map = OpenLayers.Class({
|
||||
* 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 @@ OpenLayers.Map = OpenLayers.Class({
|
||||
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.Map = OpenLayers.Class({
|
||||
* {<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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user