Adding animated zooming

This commit is contained in:
ahocevar
2012-12-23 18:47:03 +01:00
parent d2b3bded72
commit 21448d2fd5
17 changed files with 239 additions and 67 deletions

View File

@@ -387,12 +387,6 @@ OpenLayers.Map = OpenLayers.Class({
*/
autoUpdateSize: true,
/**
* Property: panTween
* {<OpenLayers.Tween>} Animated panning tween object, see panTo()
*/
panTween: null,
/**
* APIProperty: eventListeners
* {Object} If set as an option at construction, the eventListeners
@@ -402,6 +396,12 @@ OpenLayers.Map = OpenLayers.Class({
*/
eventListeners: null,
/**
* Property: panTween
* {<OpenLayers.Tween>} Animated panning tween object, see panTo()
*/
panTween: null,
/**
* APIProperty: panMethod
* {Function} The Easing function to be used for tweening. Default is
@@ -419,6 +419,28 @@ OpenLayers.Map = OpenLayers.Class({
*/
panDuration: 50,
/**
* Property: zoomTween
* {<OpenLayers.Tween>} Animated zooming tween object, see zoomTo()
*/
zoomTween: null,
/**
* APIProperty: zoomMethod
* {Function} The Easing function to be used for tweening. Default is
* OpenLayers.Easing.Quad.easeOut. Setting this to 'null' turns off
* animated zooming.
*/
zoomMethod: OpenLayers.Easing.Quad.easeOut,
/**
* Property: zoomDuration
* {Integer} The number of steps to be passed to the
* OpenLayers.Tween.start() method when the map is zoomed.
* Default is 20.
*/
zoomDuration: 20,
/**
* Property: paddingForPopups
* {<OpenLayers.Bounds>} Outside margin of the popup. Used to prevent
@@ -586,6 +608,7 @@ OpenLayers.Map = OpenLayers.Class({
this.layerContainerDiv = OpenLayers.Util.createDiv(id);
this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE['Popup']-1;
this.layerContainerOriginPx = {x: 0, y: 0};
this.applyTransform();
this.viewPortDiv.appendChild(this.layerContainerDiv);
@@ -681,6 +704,13 @@ OpenLayers.Map = OpenLayers.Class({
this.setCenter(options.center, options.zoom);
}
}
if (this.panMethod) {
this.panTween = new OpenLayers.Tween(this.panMethod);
}
if (this.zoomMethod && this.applyTransform.transform) {
this.zoomTween = new OpenLayers.Tween(this.zoomMethod);
}
},
/**
@@ -749,6 +779,11 @@ OpenLayers.Map = OpenLayers.Class({
this.panTween.stop();
this.panTween = null;
}
// make sure zooming doesn't continue after destruction
if(this.zoomTween) {
this.zoomTween.stop();
this.zoomTween = null;
}
// map has been destroyed. dont do it again!
OpenLayers.Event.stopObserving(window, 'unload', this.unloadDestroy);
@@ -1664,10 +1699,7 @@ OpenLayers.Map = OpenLayers.Class({
* lonlat - {<OpenLayers.LonLat>}
*/
panTo: function(lonlat) {
if (this.panMethod && this.getExtent().scale(this.panRatio).containsLonLat(lonlat)) {
if (!this.panTween) {
this.panTween = new OpenLayers.Tween(this.panMethod);
}
if (this.panTween && this.getExtent().scale(this.panRatio).containsLonLat(lonlat)) {
var center = this.getCachedCenter();
// center will not change, don't do nothing
@@ -1718,7 +1750,12 @@ OpenLayers.Map = OpenLayers.Class({
* TBD: reconsider forceZoomChange in 3.0
*/
setCenter: function(lonlat, zoom, dragging, forceZoomChange) {
this.panTween && this.panTween.stop();
if (this.panTween) {
this.panTween.stop();
}
if (this.zoomTween) {
this.zoomTween.stop();
}
this.moveTo(lonlat, zoom, {
'dragging': dragging,
'forceZoomChange': forceZoomChange
@@ -2319,17 +2356,65 @@ OpenLayers.Map = OpenLayers.Class({
/**
* APIMethod: zoomTo
* Zoom to a specific zoom level
* Zoom to a specific zoom level. Zooming will be animated unless the map
* is configured with {zoomMethod: null}. To zoom without animation, use
* <setCenter> without a lonlat argument.
*
* Parameters:
* zoom - {Integer}
*/
zoomTo: function(zoom) {
if (this.isValidZoomLevel(zoom)) {
this.setCenter(null, zoom);
zoomTo: function(zoom, xy) {
// non-API arguments:
// xy - {<OpenLayers.Pixel>} optional zoom origin
var map = this;
if (map.isValidZoomLevel(zoom)) {
if (map.baseLayer.wrapDateLine) {
zoom = map.adjustZoom(zoom);
}
if (map.zoomTween) {
var currentRes = map.getResolution(),
targetRes = map.getResolutionForZoom(zoom),
start = {scale: 1},
end = {scale: currentRes / targetRes};
if (map.zoomTween.playing && map.zoomTween.duration < 3 * map.zoomDuration) {
// update the end scale, and reuse the running zoomTween
map.zoomTween.finish = {
scale: map.zoomTween.finish.scale * end.scale
}
} else {
if (!xy) {
var size = map.getSize();
xy = {x: size.w / 2, y: size.h / 2};
}
map.zoomTween.start(start, end, map.zoomDuration, {
minFrameRate: 50, // don't spend much time zooming
callbacks: {
eachStep: function(data) {
var containerOrigin = map.layerContainerOriginPx,
scale = data.scale,
dx = ((scale - 1) * (containerOrigin.x - xy.x)) | 0,
dy = ((scale - 1) * (containerOrigin.y - xy.y)) | 0;
map.applyTransform(containerOrigin.x + dx, containerOrigin.y + dy, scale);
},
done: function(data) {
map.applyTransform();
var resolution = map.getResolution() / data.scale,
zoom = map.getZoomForResolution(resolution, true)
map.moveTo(map.getZoomTargetCenter(xy, resolution), zoom, true);
}
}
});
}
} else {
var center = xy ?
map.getZoomTargetCenter(xy, map.getResolutionForZoom(zoom)) :
null;
map.setCenter(center, zoom);
}
}
},
/**
* APIMethod: zoomIn
*
@@ -2487,7 +2572,32 @@ OpenLayers.Map = OpenLayers.Class({
return px;
},
/**
* Method: getZoomTargetCenter
*
* Parameters:
* xy - {<OpenLayers.Pixel>} The zoom origin pixel location on the screen
* resolution - {Float} The resolution we want to get the center for
*
* Returns:
* {<OpenLayers.LonLat>} The location of the map center after the
* transformation described by the origin xy and the target resolution.
*/
getZoomTargetCenter: function (xy, resolution) {
var lonlat = null,
size = this.getSize(),
deltaX = size.w/2 - xy.x,
deltaY = xy.y - size.h/2,
zoomPoint = this.getLonLatFromPixel(xy);
if (zoomPoint) {
lonlat = new OpenLayers.LonLat(
zoomPoint.lon + deltaX * resolution,
zoomPoint.lat + deltaY * resolution
);
}
return lonlat;
},
//
// CONVENIENCE TRANSLATION FUNCTIONS FOR API
//