removed psuedo private accessors and properties in favor of direct access. cleaned up some formatting for readability

This commit is contained in:
thatcher 2012-01-04 18:14:20 -05:00
parent 878269e0e9
commit 21753e6800
3 changed files with 414 additions and 274 deletions

View File

@ -3061,57 +3061,54 @@ $.Spring = function( options ) {
this.current = { this.current = {
point: typeof ( this.initial ) == "number" ? value: typeof ( this.initial ) == "number" ?
this.initial : this.initial :
0, 0,
time: new Date().getTime() // always work in milliseconds time: new Date().getTime() // always work in milliseconds
} };
this.startValue = this.current.point; this.start = {
this.startTime = this.current.time; value: this.current.value,
time: this.current.time
};
this.targetValue = this.current.point; this.target = {
this.targetTime = this.current.time; value: this.current.value,
time: this.current.time
};
}; };
$.Spring.prototype = { $.Spring.prototype = {
getCurrent: function() {
return this.current.point;
},
getTarget: function() {
return this.targetValue;
},
resetTo: function( target ) { resetTo: function( target ) {
this.targetValue = target; this.target.value = target;
this.targetTime = this.current.time; this.target.time = this.current.time;
this.startValue = this.targetValue; this.start.value = this.target.value;
this.startTime = this.targetTime; this.start.time = this.target.time;
}, },
springTo: function( target ) { springTo: function( target ) {
this.startValue = this.current.point; this.start.value = this.current.value;
this.startTime = this.current.time; this.start.time = this.current.time;
this.targetValue = target; this.target.value = target;
this.targetTime = this.startTime + 1000 * this.animationTime; this.target.time = this.start.time + 1000 * this.animationTime;
}, },
shiftBy: function( delta ) { shiftBy: function( delta ) {
this.startValue += delta; this.start.value += delta;
this.targetValue += delta; this.target.value += delta;
}, },
update: function() { update: function() {
this.current.time = new Date().getTime(); this.current.time = new Date().getTime();
this.current.point = (this.current.time >= this.targetTime) ? this.current.value = (this.current.time >= this.target.time) ?
this.targetValue : this.target.value :
this.startValue + this.start.value +
(this.targetValue - this.startValue) * ( this.target.value - this.start.value ) *
transform( transform(
this.springStiffness, this.springStiffness,
(this.current.time - this.startTime) / ( this.current.time - this.start.time ) /
(this.targetTime - this.startTime) ( this.target.time - this.start.time )
); );
} }
} }
@ -4008,60 +4005,92 @@ function finishLoadingImage( image, callback, successful, jobid ){
$.Viewport = function(containerSize, contentSize, config) { $.Viewport = function(containerSize, contentSize, config) {
this.zoomPoint = null; this.zoomPoint = null;
this.config = config; this.config = config;
this._containerSize = containerSize; this.containerSize = containerSize;
this._contentSize = contentSize; this.contentSize = contentSize;
this._contentAspect = contentSize.x / contentSize.y; this.contentAspect = contentSize.x / contentSize.y;
this._contentHeight = contentSize.y / contentSize.x; this.contentHeight = contentSize.y / contentSize.x;
this._centerSpringX = new $.Spring(0, this.config); this.centerSpringX = new $.Spring({
this._centerSpringY = new $.Spring(0, this.config); initial: 0,
this._zoomSpring = new $.Spring(1, this.config); springStiffness: config.springStiffness,
this._homeBounds = new $.Rect(0, 0, 1, this._contentHeight); animationTime: config.animationTime
});
this.centerSpringY = new $.Spring({
initial: 0,
springStiffness: config.springStiffness,
animationTime: config.animationTime
});
this.zoomSpring = new $.Spring({
initial: 1,
springStiffness: config.springStiffness,
animationTime: config.animationTime
});
this.minZoomImageRatio = config.minZoomImageRatio;
this.maxZoomPixelRatio = config.maxZoomPixelRatio;
this.visibilityRatio = config.visibilityRatio;
this.wrapHorizontal = config.wrapHorizontal;
this.wrapVertical = config.wrapVertical;
this.homeBounds = new $.Rect(0, 0, 1, this.contentHeight);
this.goHome(true); this.goHome(true);
this.update(); this.update();
}; };
$.Viewport.prototype = { $.Viewport.prototype = {
_getHomeZoom: function() { getHomeZoom: function() {
var aspectFactor = this._contentAspect / this.getAspectRatio(); var aspectFactor = this.contentAspect / this.getAspectRatio();
return (aspectFactor >= 1) ? 1 : aspectFactor; return (aspectFactor >= 1) ? 1 : aspectFactor;
}, },
_getMinZoom: function() { getMinZoom: function() {
var homeZoom = this._getHomeZoom(); var homeZoom = this.getHomeZoom()
var zoom = this.config.minZoomImageRatio * homeZoom; zoom = this.minZoomImageRatio * homeZoom;
return Math.min(zoom, homeZoom); return Math.min(zoom, homeZoom);
}, },
_getMaxZoom: function() { getMaxZoom: function() {
var zoom = this._contentSize.x * this.config.maxZoomPixelRatio / this._containerSize.x; var zoom = this.contentSize.x *
return Math.max(zoom, this._getHomeZoom()); this.maxZoomPixelRatio / this.containerSize.x;
return Math.max(zoom, this.getHomeZoom());
}, },
getAspectRatio: function() { getAspectRatio: function() {
return this._containerSize.x / this._containerSize.y; return this.containerSize.x / this.containerSize.y;
}, },
getContainerSize: function() { getContainerSize: function() {
return new $.Point(this._containerSize.x, this._containerSize.y); return new $.Point(this.containerSize.x, this.containerSize.y);
}, },
getBounds: function(current) { getBounds: function(current) {
var center = this.getCenter(current); var center = this.getCenter(current),
var width = 1.0 / this.getZoom(current); width = 1.0 / this.getZoom(current),
var height = width / this.getAspectRatio(); height = width / this.getAspectRatio();
return new $.Rect(center.x - width / 2.0, center.y - height / 2.0, return new $.Rect(
width, height); center.x - width / 2.0,
center.y - height / 2.0,
width,
height
);
}, },
getCenter: function(current) { getCenter: function(current) {
var centerCurrent = new $.Point( var centerCurrent = new $.Point(
this._centerSpringX.getCurrent(), this.centerSpringX.current.value,
this._centerSpringY.getCurrent() this.centerSpringY.current.value
); ),
var centerTarget = new $.Point( centerTarget = new $.Point(
this._centerSpringX.getTarget(), this.centerSpringX.target.value,
this._centerSpringY.getTarget() this.centerSpringY.target.value
); ),
oldZoomPixel,
zoom,
width,
height,
bounds,
newZoomPixel,
deltaZoomPixels,
deltaZoomPoints;
if (current) { if (current) {
return centerCurrent; return centerCurrent;
@ -4069,39 +4098,47 @@ $.Viewport.prototype = {
return centerTarget; return centerTarget;
} }
var oldZoomPixel = this.pixelFromPoint(this.zoomPoint, true); oldZoomPixel = this.pixelFromPoint(this.zoomPoint, true);
var zoom = this.getZoom(); zoom = this.getZoom();
var width = 1.0 / zoom; width = 1.0 / zoom;
var height = width / this.getAspectRatio(); height = width / this.getAspectRatio();
var bounds = new $.Rect(centerCurrent.x - width / 2.0, bounds = new $.Rect(
centerCurrent.y - height / 2.0, width, height); centerCurrent.x - width / 2.0,
centerCurrent.y - height / 2.0,
width,
height
);
var newZoomPixel = this.zoomPoint.minus(bounds.getTopLeft()).times(this._containerSize.x / bounds.width); newZoomPixel = this.zoomPoint.minus(
var deltaZoomPixels = newZoomPixel.minus(oldZoomPixel); bounds.getTopLeft()
var deltaZoomPoints = deltaZoomPixels.divide(this._containerSize.x * zoom); ).times(
this.containerSize.x / bounds.width
);
deltaZoomPixels = newZoomPixel.minus( oldZoomPixel );
deltaZoomPoints = deltaZoomPixels.divide( this.containerSize.x * zoom );
return centerTarget.plus( deltaZoomPoints ); return centerTarget.plus( deltaZoomPoints );
}, },
getZoom: function(current) { getZoom: function(current) {
if (current) { if (current) {
return this._zoomSpring.getCurrent(); return this.zoomSpring.current.value;
} else { } else {
return this._zoomSpring.getTarget(); return this.zoomSpring.target.value;
} }
}, },
applyConstraints: function(immediately) { applyConstraints: function(immediately) {
var actualZoom = this.getZoom(); var actualZoom = this.getZoom();
var constrainedZoom = Math.max(Math.min(actualZoom, this._getMaxZoom()), this._getMinZoom()); var constrainedZoom = Math.max(Math.min(actualZoom, this.getMaxZoom()), this.getMinZoom());
if (actualZoom != constrainedZoom) { if (actualZoom != constrainedZoom) {
this.zoomTo(constrainedZoom, this.zoomPoint, immediately); this.zoomTo(constrainedZoom, this.zoomPoint, immediately);
} }
var bounds = this.getBounds(); var bounds = this.getBounds();
var visibilityRatio = this.config.visibilityRatio; var visibilityRatio = this.visibilityRatio;
var horThres = visibilityRatio * bounds.width; var horThres = visibilityRatio * bounds.width;
var verThres = visibilityRatio * bounds.height; var verThres = visibilityRatio * bounds.height;
@ -4109,10 +4146,10 @@ $.Viewport.prototype = {
var left = bounds.x + bounds.width; var left = bounds.x + bounds.width;
var right = 1 - bounds.x; var right = 1 - bounds.x;
var top = bounds.y + bounds.height; var top = bounds.y + bounds.height;
var bottom = this._contentHeight - bounds.y; var bottom = this.contentHeight - bounds.y;
var dx = 0; var dx = 0;
if (this.config.wrapHorizontal) { if ( this.wrapHorizontal ) {
} else if (left < horThres) { } else if (left < horThres) {
dx = horThres - left; dx = horThres - left;
} else if (right < horThres) { } else if (right < horThres) {
@ -4120,7 +4157,7 @@ $.Viewport.prototype = {
} }
var dy = 0; var dy = 0;
if (this.config.wrapVertical) { if ( this.wrapVertical ) {
} else if (top < verThres) { } else if (top < verThres) {
dy = verThres - top; dy = verThres - top;
} else if (bottom < verThres) { } else if (bottom < verThres) {
@ -4139,10 +4176,19 @@ $.Viewport.prototype = {
}, },
fitBounds: function(bounds, immediately) { fitBounds: function(bounds, immediately) {
var aspect = this.getAspectRatio(); var aspect = this.getAspectRatio(),
var center = bounds.getCenter(); center = bounds.getCenter(),
newBounds = new $.Rect(
bounds.x,
bounds.y,
bounds.width,
bounds.height
),
oldBounds,
oldZoom,
newZoom,
refPoint;
var newBounds = new $.Rect(bounds.x, bounds.y, bounds.width, bounds.height);
if (newBounds.getAspectRatio() >= aspect) { if (newBounds.getAspectRatio() >= aspect) {
newBounds.height = bounds.width / aspect; newBounds.height = bounds.width / aspect;
newBounds.y = center.y - newBounds.height / 2; newBounds.y = center.y - newBounds.height / 2;
@ -4154,18 +4200,24 @@ $.Viewport.prototype = {
this.panTo(this.getCenter(true), true); this.panTo(this.getCenter(true), true);
this.zoomTo(this.getZoom(true), null, true); this.zoomTo(this.getZoom(true), null, true);
var oldBounds = this.getBounds(); oldBounds = this.getBounds();
var oldZoom = this.getZoom(); oldZoom = this.getZoom();
newZoom = 1.0 / newBounds.width;
var newZoom = 1.0 / newBounds.width;
if (newZoom == oldZoom || newBounds.width == oldBounds.width) { if (newZoom == oldZoom || newBounds.width == oldBounds.width) {
this.panTo( center, immediately ); this.panTo( center, immediately );
return; return;
} }
var refPoint = oldBounds.getTopLeft().times(this._containerSize.x / oldBounds.width).minus( refPoint = oldBounds.getTopLeft().times(
newBounds.getTopLeft().times(this._containerSize.x / newBounds.width)).divide( this.containerSize.x / oldBounds.width
this._containerSize.x / oldBounds.width - this._containerSize.x / newBounds.width); ).minus(
newBounds.getTopLeft().times(
this.containerSize.x / newBounds.width
)
).divide(
this.containerSize.x / oldBounds.width -
this.containerSize.x / newBounds.width
);
this.zoomTo( newZoom, refPoint, immediately ); this.zoomTo( newZoom, refPoint, immediately );
@ -4174,58 +4226,60 @@ $.Viewport.prototype = {
goHome: function(immediately) { goHome: function(immediately) {
var center = this.getCenter(); var center = this.getCenter();
if (this.config.wrapHorizontal) { if ( this.wrapHorizontal ) {
center.x = (1 + (center.x % 1)) % 1; center.x = (1 + (center.x % 1)) % 1;
this._centerSpringX.resetTo(center.x); this.centerSpringX.resetTo(center.x);
this._centerSpringX.update(); this.centerSpringX.update();
} }
if (this.config.wrapVertical) { if ( this.wrapVertical ) {
center.y = (this._contentHeight + (center.y % this._contentHeight)) % this._contentHeight; center.y = (this.contentHeight + (center.y % this.contentHeight)) % this.contentHeight;
this._centerSpringY.resetTo(center.y); this.centerSpringY.resetTo(center.y);
this._centerSpringY.update(); this.centerSpringY.update();
} }
this.fitBounds(this._homeBounds, immediately); this.fitBounds(this.homeBounds, immediately);
}, },
panBy: function(delta, immediately) { panBy: function(delta, immediately) {
var center = new $.Point(this._centerSpringX.getTarget(), var center = new $.Point(
this._centerSpringY.getTarget()); this.centerSpringX.target.value,
this.centerSpringY.target.value
);
this.panTo( center.plus( delta ), immediately ); this.panTo( center.plus( delta ), immediately );
}, },
panTo: function(center, immediately) { panTo: function(center, immediately) {
if (immediately) { if (immediately) {
this._centerSpringX.resetTo(center.x); this.centerSpringX.resetTo(center.x);
this._centerSpringY.resetTo(center.y); this.centerSpringY.resetTo(center.y);
} else { } else {
this._centerSpringX.springTo(center.x); this.centerSpringX.springTo(center.x);
this._centerSpringY.springTo(center.y); this.centerSpringY.springTo(center.y);
} }
}, },
zoomBy: function(factor, refPoint, immediately) { zoomBy: function(factor, refPoint, immediately) {
this.zoomTo(this._zoomSpring.getTarget() * factor, refPoint, immediately); this.zoomTo(this.zoomSpring.target.value * factor, refPoint, immediately);
}, },
zoomTo: function(zoom, refPoint, immediately) { zoomTo: function(zoom, refPoint, immediately) {
if (immediately) { if (immediately) {
this._zoomSpring.resetTo(zoom); this.zoomSpring.resetTo(zoom);
} else { } else {
this._zoomSpring.springTo(zoom); this.zoomSpring.springTo(zoom);
} }
this.zoomPoint = refPoint instanceof $.Point ? refPoint : null; this.zoomPoint = refPoint instanceof $.Point ? refPoint : null;
}, },
resize: function(newContainerSize, maintain) { resize: function(newContainerSize, maintain) {
var oldBounds = this.getBounds(); var oldBounds = this.getBounds(),
var newBounds = oldBounds; newBounds = oldBounds,
var widthDeltaFactor = newContainerSize.x / this._containerSize.x; widthDeltaFactor = newContainerSize.x / this.containerSize.x;
this._containerSize = new $.Point(newContainerSize.x, newContainerSize.y); this.containerSize = new $.Point(newContainerSize.x, newContainerSize.y);
if (maintain) { if (maintain) {
newBounds.width = oldBounds.width * widthDeltaFactor; newBounds.width = oldBounds.width * widthDeltaFactor;
@ -4236,52 +4290,68 @@ $.Viewport.prototype = {
}, },
update: function() { update: function() {
var oldCenterX = this._centerSpringX.getCurrent(); var oldCenterX = this.centerSpringX.current.value,
var oldCenterY = this._centerSpringY.getCurrent(); oldCenterY = this.centerSpringY.current.value,
var oldZoom = this._zoomSpring.getCurrent(); oldZoom = this.zoomSpring.current.value,
oldZoomPixel,
newZoomPixel,
deltaZoomPixels,
deltaZoomPoints;
if (this.zoomPoint) { if (this.zoomPoint) {
var oldZoomPixel = this.pixelFromPoint(this.zoomPoint, true); oldZoomPixel = this.pixelFromPoint(this.zoomPoint, true);
} }
this._zoomSpring.update(); this.zoomSpring.update();
if (this.zoomPoint && this._zoomSpring.getCurrent() != oldZoom) { if (this.zoomPoint && this.zoomSpring.current.value != oldZoom) {
var newZoomPixel = this.pixelFromPoint(this.zoomPoint, true); newZoomPixel = this.pixelFromPoint( this.zoomPoint, true );
var deltaZoomPixels = newZoomPixel.minus(oldZoomPixel); deltaZoomPixels = newZoomPixel.minus( oldZoomPixel);
var deltaZoomPoints = this.deltaPointsFromPixels(deltaZoomPixels, true); deltaZoomPoints = this.deltaPointsFromPixels( deltaZoomPixels, true );
this._centerSpringX.shiftBy(deltaZoomPoints.x); this.centerSpringX.shiftBy( deltaZoomPoints.x );
this._centerSpringY.shiftBy(deltaZoomPoints.y); this.centerSpringY.shiftBy( deltaZoomPoints.y );
} else { } else {
this.zoomPoint = null; this.zoomPoint = null;
} }
this._centerSpringX.update(); this.centerSpringX.update();
this._centerSpringY.update(); this.centerSpringY.update();
return this._centerSpringX.getCurrent() != oldCenterX || return this.centerSpringX.current.value != oldCenterX ||
this._centerSpringY.getCurrent() != oldCenterY || this.centerSpringY.current.value != oldCenterY ||
this._zoomSpring.getCurrent() != oldZoom; this.zoomSpring.current.value != oldZoom;
}, },
deltaPixelsFromPoints: function(deltaPoints, current) { deltaPixelsFromPoints: function(deltaPoints, current) {
return deltaPoints.times(this._containerSize.x * this.getZoom(current)); return deltaPoints.times(
this.containerSize.x * this.getZoom( current )
);
}, },
deltaPointsFromPixels: function(deltaPixels, current) { deltaPointsFromPixels: function(deltaPixels, current) {
return deltaPixels.divide(this._containerSize.x * this.getZoom(current)); return deltaPixels.divide(
this.containerSize.x * this.getZoom( current )
);
}, },
pixelFromPoint: function(point, current) { pixelFromPoint: function(point, current) {
var bounds = this.getBounds( current ); var bounds = this.getBounds( current );
return point.minus(bounds.getTopLeft()).times(this._containerSize.x / bounds.width); return point.minus(
bounds.getTopLeft()
).times(
this.containerSize.x / bounds.width
);
}, },
pointFromPixel: function(pixel, current) { pointFromPixel: function(pixel, current) {
var bounds = this.getBounds( current ); var bounds = this.getBounds( current );
return pixel.divide(this._containerSize.x / bounds.width).plus(bounds.getTopLeft()); return pixel.divide(
this.containerSize.x / bounds.width
).plus(
bounds.getTopLeft()
);
} }
}; };

View File

@ -24,57 +24,54 @@ $.Spring = function( options ) {
this.current = { this.current = {
point: typeof ( this.initial ) == "number" ? value: typeof ( this.initial ) == "number" ?
this.initial : this.initial :
0, 0,
time: new Date().getTime() // always work in milliseconds time: new Date().getTime() // always work in milliseconds
} };
this.startValue = this.current.point; this.start = {
this.startTime = this.current.time; value: this.current.value,
time: this.current.time
};
this.targetValue = this.current.point; this.target = {
this.targetTime = this.current.time; value: this.current.value,
time: this.current.time
};
}; };
$.Spring.prototype = { $.Spring.prototype = {
getCurrent: function() {
return this.current.point;
},
getTarget: function() {
return this.targetValue;
},
resetTo: function( target ) { resetTo: function( target ) {
this.targetValue = target; this.target.value = target;
this.targetTime = this.current.time; this.target.time = this.current.time;
this.startValue = this.targetValue; this.start.value = this.target.value;
this.startTime = this.targetTime; this.start.time = this.target.time;
}, },
springTo: function( target ) { springTo: function( target ) {
this.startValue = this.current.point; this.start.value = this.current.value;
this.startTime = this.current.time; this.start.time = this.current.time;
this.targetValue = target; this.target.value = target;
this.targetTime = this.startTime + 1000 * this.animationTime; this.target.time = this.start.time + 1000 * this.animationTime;
}, },
shiftBy: function( delta ) { shiftBy: function( delta ) {
this.startValue += delta; this.start.value += delta;
this.targetValue += delta; this.target.value += delta;
}, },
update: function() { update: function() {
this.current.time = new Date().getTime(); this.current.time = new Date().getTime();
this.current.point = (this.current.time >= this.targetTime) ? this.current.value = (this.current.time >= this.target.time) ?
this.targetValue : this.target.value :
this.startValue + this.start.value +
(this.targetValue - this.startValue) * ( this.target.value - this.start.value ) *
transform( transform(
this.springStiffness, this.springStiffness,
(this.current.time - this.startTime) / ( this.current.time - this.start.time ) /
(this.targetTime - this.startTime) ( this.target.time - this.start.time )
); );
} }
} }

View File

@ -4,60 +4,92 @@
$.Viewport = function(containerSize, contentSize, config) { $.Viewport = function(containerSize, contentSize, config) {
this.zoomPoint = null; this.zoomPoint = null;
this.config = config; this.config = config;
this._containerSize = containerSize; this.containerSize = containerSize;
this._contentSize = contentSize; this.contentSize = contentSize;
this._contentAspect = contentSize.x / contentSize.y; this.contentAspect = contentSize.x / contentSize.y;
this._contentHeight = contentSize.y / contentSize.x; this.contentHeight = contentSize.y / contentSize.x;
this._centerSpringX = new $.Spring(0, this.config); this.centerSpringX = new $.Spring({
this._centerSpringY = new $.Spring(0, this.config); initial: 0,
this._zoomSpring = new $.Spring(1, this.config); springStiffness: config.springStiffness,
this._homeBounds = new $.Rect(0, 0, 1, this._contentHeight); animationTime: config.animationTime
});
this.centerSpringY = new $.Spring({
initial: 0,
springStiffness: config.springStiffness,
animationTime: config.animationTime
});
this.zoomSpring = new $.Spring({
initial: 1,
springStiffness: config.springStiffness,
animationTime: config.animationTime
});
this.minZoomImageRatio = config.minZoomImageRatio;
this.maxZoomPixelRatio = config.maxZoomPixelRatio;
this.visibilityRatio = config.visibilityRatio;
this.wrapHorizontal = config.wrapHorizontal;
this.wrapVertical = config.wrapVertical;
this.homeBounds = new $.Rect(0, 0, 1, this.contentHeight);
this.goHome(true); this.goHome(true);
this.update(); this.update();
}; };
$.Viewport.prototype = { $.Viewport.prototype = {
_getHomeZoom: function() { getHomeZoom: function() {
var aspectFactor = this._contentAspect / this.getAspectRatio(); var aspectFactor = this.contentAspect / this.getAspectRatio();
return (aspectFactor >= 1) ? 1 : aspectFactor; return (aspectFactor >= 1) ? 1 : aspectFactor;
}, },
_getMinZoom: function() { getMinZoom: function() {
var homeZoom = this._getHomeZoom(); var homeZoom = this.getHomeZoom()
var zoom = this.config.minZoomImageRatio * homeZoom; zoom = this.minZoomImageRatio * homeZoom;
return Math.min(zoom, homeZoom); return Math.min(zoom, homeZoom);
}, },
_getMaxZoom: function() { getMaxZoom: function() {
var zoom = this._contentSize.x * this.config.maxZoomPixelRatio / this._containerSize.x; var zoom = this.contentSize.x *
return Math.max(zoom, this._getHomeZoom()); this.maxZoomPixelRatio / this.containerSize.x;
return Math.max(zoom, this.getHomeZoom());
}, },
getAspectRatio: function() { getAspectRatio: function() {
return this._containerSize.x / this._containerSize.y; return this.containerSize.x / this.containerSize.y;
}, },
getContainerSize: function() { getContainerSize: function() {
return new $.Point(this._containerSize.x, this._containerSize.y); return new $.Point(this.containerSize.x, this.containerSize.y);
}, },
getBounds: function(current) { getBounds: function(current) {
var center = this.getCenter(current); var center = this.getCenter(current),
var width = 1.0 / this.getZoom(current); width = 1.0 / this.getZoom(current),
var height = width / this.getAspectRatio(); height = width / this.getAspectRatio();
return new $.Rect(center.x - width / 2.0, center.y - height / 2.0, return new $.Rect(
width, height); center.x - width / 2.0,
center.y - height / 2.0,
width,
height
);
}, },
getCenter: function(current) { getCenter: function(current) {
var centerCurrent = new $.Point( var centerCurrent = new $.Point(
this._centerSpringX.getCurrent(), this.centerSpringX.current.value,
this._centerSpringY.getCurrent() this.centerSpringY.current.value
); ),
var centerTarget = new $.Point( centerTarget = new $.Point(
this._centerSpringX.getTarget(), this.centerSpringX.target.value,
this._centerSpringY.getTarget() this.centerSpringY.target.value
); ),
oldZoomPixel,
zoom,
width,
height,
bounds,
newZoomPixel,
deltaZoomPixels,
deltaZoomPoints;
if (current) { if (current) {
return centerCurrent; return centerCurrent;
@ -65,39 +97,47 @@ $.Viewport.prototype = {
return centerTarget; return centerTarget;
} }
var oldZoomPixel = this.pixelFromPoint(this.zoomPoint, true); oldZoomPixel = this.pixelFromPoint(this.zoomPoint, true);
var zoom = this.getZoom(); zoom = this.getZoom();
var width = 1.0 / zoom; width = 1.0 / zoom;
var height = width / this.getAspectRatio(); height = width / this.getAspectRatio();
var bounds = new $.Rect(centerCurrent.x - width / 2.0, bounds = new $.Rect(
centerCurrent.y - height / 2.0, width, height); centerCurrent.x - width / 2.0,
centerCurrent.y - height / 2.0,
width,
height
);
var newZoomPixel = this.zoomPoint.minus(bounds.getTopLeft()).times(this._containerSize.x / bounds.width); newZoomPixel = this.zoomPoint.minus(
var deltaZoomPixels = newZoomPixel.minus(oldZoomPixel); bounds.getTopLeft()
var deltaZoomPoints = deltaZoomPixels.divide(this._containerSize.x * zoom); ).times(
this.containerSize.x / bounds.width
);
deltaZoomPixels = newZoomPixel.minus( oldZoomPixel );
deltaZoomPoints = deltaZoomPixels.divide( this.containerSize.x * zoom );
return centerTarget.plus( deltaZoomPoints ); return centerTarget.plus( deltaZoomPoints );
}, },
getZoom: function(current) { getZoom: function(current) {
if (current) { if (current) {
return this._zoomSpring.getCurrent(); return this.zoomSpring.current.value;
} else { } else {
return this._zoomSpring.getTarget(); return this.zoomSpring.target.value;
} }
}, },
applyConstraints: function(immediately) { applyConstraints: function(immediately) {
var actualZoom = this.getZoom(); var actualZoom = this.getZoom();
var constrainedZoom = Math.max(Math.min(actualZoom, this._getMaxZoom()), this._getMinZoom()); var constrainedZoom = Math.max(Math.min(actualZoom, this.getMaxZoom()), this.getMinZoom());
if (actualZoom != constrainedZoom) { if (actualZoom != constrainedZoom) {
this.zoomTo(constrainedZoom, this.zoomPoint, immediately); this.zoomTo(constrainedZoom, this.zoomPoint, immediately);
} }
var bounds = this.getBounds(); var bounds = this.getBounds();
var visibilityRatio = this.config.visibilityRatio; var visibilityRatio = this.visibilityRatio;
var horThres = visibilityRatio * bounds.width; var horThres = visibilityRatio * bounds.width;
var verThres = visibilityRatio * bounds.height; var verThres = visibilityRatio * bounds.height;
@ -105,10 +145,10 @@ $.Viewport.prototype = {
var left = bounds.x + bounds.width; var left = bounds.x + bounds.width;
var right = 1 - bounds.x; var right = 1 - bounds.x;
var top = bounds.y + bounds.height; var top = bounds.y + bounds.height;
var bottom = this._contentHeight - bounds.y; var bottom = this.contentHeight - bounds.y;
var dx = 0; var dx = 0;
if (this.config.wrapHorizontal) { if ( this.wrapHorizontal ) {
} else if (left < horThres) { } else if (left < horThres) {
dx = horThres - left; dx = horThres - left;
} else if (right < horThres) { } else if (right < horThres) {
@ -116,7 +156,7 @@ $.Viewport.prototype = {
} }
var dy = 0; var dy = 0;
if (this.config.wrapVertical) { if ( this.wrapVertical ) {
} else if (top < verThres) { } else if (top < verThres) {
dy = verThres - top; dy = verThres - top;
} else if (bottom < verThres) { } else if (bottom < verThres) {
@ -135,10 +175,19 @@ $.Viewport.prototype = {
}, },
fitBounds: function(bounds, immediately) { fitBounds: function(bounds, immediately) {
var aspect = this.getAspectRatio(); var aspect = this.getAspectRatio(),
var center = bounds.getCenter(); center = bounds.getCenter(),
newBounds = new $.Rect(
bounds.x,
bounds.y,
bounds.width,
bounds.height
),
oldBounds,
oldZoom,
newZoom,
refPoint;
var newBounds = new $.Rect(bounds.x, bounds.y, bounds.width, bounds.height);
if (newBounds.getAspectRatio() >= aspect) { if (newBounds.getAspectRatio() >= aspect) {
newBounds.height = bounds.width / aspect; newBounds.height = bounds.width / aspect;
newBounds.y = center.y - newBounds.height / 2; newBounds.y = center.y - newBounds.height / 2;
@ -150,18 +199,24 @@ $.Viewport.prototype = {
this.panTo(this.getCenter(true), true); this.panTo(this.getCenter(true), true);
this.zoomTo(this.getZoom(true), null, true); this.zoomTo(this.getZoom(true), null, true);
var oldBounds = this.getBounds(); oldBounds = this.getBounds();
var oldZoom = this.getZoom(); oldZoom = this.getZoom();
newZoom = 1.0 / newBounds.width;
var newZoom = 1.0 / newBounds.width;
if (newZoom == oldZoom || newBounds.width == oldBounds.width) { if (newZoom == oldZoom || newBounds.width == oldBounds.width) {
this.panTo( center, immediately ); this.panTo( center, immediately );
return; return;
} }
var refPoint = oldBounds.getTopLeft().times(this._containerSize.x / oldBounds.width).minus( refPoint = oldBounds.getTopLeft().times(
newBounds.getTopLeft().times(this._containerSize.x / newBounds.width)).divide( this.containerSize.x / oldBounds.width
this._containerSize.x / oldBounds.width - this._containerSize.x / newBounds.width); ).minus(
newBounds.getTopLeft().times(
this.containerSize.x / newBounds.width
)
).divide(
this.containerSize.x / oldBounds.width -
this.containerSize.x / newBounds.width
);
this.zoomTo( newZoom, refPoint, immediately ); this.zoomTo( newZoom, refPoint, immediately );
@ -170,58 +225,60 @@ $.Viewport.prototype = {
goHome: function(immediately) { goHome: function(immediately) {
var center = this.getCenter(); var center = this.getCenter();
if (this.config.wrapHorizontal) { if ( this.wrapHorizontal ) {
center.x = (1 + (center.x % 1)) % 1; center.x = (1 + (center.x % 1)) % 1;
this._centerSpringX.resetTo(center.x); this.centerSpringX.resetTo(center.x);
this._centerSpringX.update(); this.centerSpringX.update();
} }
if (this.config.wrapVertical) { if ( this.wrapVertical ) {
center.y = (this._contentHeight + (center.y % this._contentHeight)) % this._contentHeight; center.y = (this.contentHeight + (center.y % this.contentHeight)) % this.contentHeight;
this._centerSpringY.resetTo(center.y); this.centerSpringY.resetTo(center.y);
this._centerSpringY.update(); this.centerSpringY.update();
} }
this.fitBounds(this._homeBounds, immediately); this.fitBounds(this.homeBounds, immediately);
}, },
panBy: function(delta, immediately) { panBy: function(delta, immediately) {
var center = new $.Point(this._centerSpringX.getTarget(), var center = new $.Point(
this._centerSpringY.getTarget()); this.centerSpringX.target.value,
this.centerSpringY.target.value
);
this.panTo( center.plus( delta ), immediately ); this.panTo( center.plus( delta ), immediately );
}, },
panTo: function(center, immediately) { panTo: function(center, immediately) {
if (immediately) { if (immediately) {
this._centerSpringX.resetTo(center.x); this.centerSpringX.resetTo(center.x);
this._centerSpringY.resetTo(center.y); this.centerSpringY.resetTo(center.y);
} else { } else {
this._centerSpringX.springTo(center.x); this.centerSpringX.springTo(center.x);
this._centerSpringY.springTo(center.y); this.centerSpringY.springTo(center.y);
} }
}, },
zoomBy: function(factor, refPoint, immediately) { zoomBy: function(factor, refPoint, immediately) {
this.zoomTo(this._zoomSpring.getTarget() * factor, refPoint, immediately); this.zoomTo(this.zoomSpring.target.value * factor, refPoint, immediately);
}, },
zoomTo: function(zoom, refPoint, immediately) { zoomTo: function(zoom, refPoint, immediately) {
if (immediately) { if (immediately) {
this._zoomSpring.resetTo(zoom); this.zoomSpring.resetTo(zoom);
} else { } else {
this._zoomSpring.springTo(zoom); this.zoomSpring.springTo(zoom);
} }
this.zoomPoint = refPoint instanceof $.Point ? refPoint : null; this.zoomPoint = refPoint instanceof $.Point ? refPoint : null;
}, },
resize: function(newContainerSize, maintain) { resize: function(newContainerSize, maintain) {
var oldBounds = this.getBounds(); var oldBounds = this.getBounds(),
var newBounds = oldBounds; newBounds = oldBounds,
var widthDeltaFactor = newContainerSize.x / this._containerSize.x; widthDeltaFactor = newContainerSize.x / this.containerSize.x;
this._containerSize = new $.Point(newContainerSize.x, newContainerSize.y); this.containerSize = new $.Point(newContainerSize.x, newContainerSize.y);
if (maintain) { if (maintain) {
newBounds.width = oldBounds.width * widthDeltaFactor; newBounds.width = oldBounds.width * widthDeltaFactor;
@ -232,52 +289,68 @@ $.Viewport.prototype = {
}, },
update: function() { update: function() {
var oldCenterX = this._centerSpringX.getCurrent(); var oldCenterX = this.centerSpringX.current.value,
var oldCenterY = this._centerSpringY.getCurrent(); oldCenterY = this.centerSpringY.current.value,
var oldZoom = this._zoomSpring.getCurrent(); oldZoom = this.zoomSpring.current.value,
oldZoomPixel,
newZoomPixel,
deltaZoomPixels,
deltaZoomPoints;
if (this.zoomPoint) { if (this.zoomPoint) {
var oldZoomPixel = this.pixelFromPoint(this.zoomPoint, true); oldZoomPixel = this.pixelFromPoint(this.zoomPoint, true);
} }
this._zoomSpring.update(); this.zoomSpring.update();
if (this.zoomPoint && this._zoomSpring.getCurrent() != oldZoom) { if (this.zoomPoint && this.zoomSpring.current.value != oldZoom) {
var newZoomPixel = this.pixelFromPoint(this.zoomPoint, true); newZoomPixel = this.pixelFromPoint( this.zoomPoint, true );
var deltaZoomPixels = newZoomPixel.minus(oldZoomPixel); deltaZoomPixels = newZoomPixel.minus( oldZoomPixel);
var deltaZoomPoints = this.deltaPointsFromPixels(deltaZoomPixels, true); deltaZoomPoints = this.deltaPointsFromPixels( deltaZoomPixels, true );
this._centerSpringX.shiftBy(deltaZoomPoints.x); this.centerSpringX.shiftBy( deltaZoomPoints.x );
this._centerSpringY.shiftBy(deltaZoomPoints.y); this.centerSpringY.shiftBy( deltaZoomPoints.y );
} else { } else {
this.zoomPoint = null; this.zoomPoint = null;
} }
this._centerSpringX.update(); this.centerSpringX.update();
this._centerSpringY.update(); this.centerSpringY.update();
return this._centerSpringX.getCurrent() != oldCenterX || return this.centerSpringX.current.value != oldCenterX ||
this._centerSpringY.getCurrent() != oldCenterY || this.centerSpringY.current.value != oldCenterY ||
this._zoomSpring.getCurrent() != oldZoom; this.zoomSpring.current.value != oldZoom;
}, },
deltaPixelsFromPoints: function(deltaPoints, current) { deltaPixelsFromPoints: function(deltaPoints, current) {
return deltaPoints.times(this._containerSize.x * this.getZoom(current)); return deltaPoints.times(
this.containerSize.x * this.getZoom( current )
);
}, },
deltaPointsFromPixels: function(deltaPixels, current) { deltaPointsFromPixels: function(deltaPixels, current) {
return deltaPixels.divide(this._containerSize.x * this.getZoom(current)); return deltaPixels.divide(
this.containerSize.x * this.getZoom( current )
);
}, },
pixelFromPoint: function(point, current) { pixelFromPoint: function(point, current) {
var bounds = this.getBounds( current ); var bounds = this.getBounds( current );
return point.minus(bounds.getTopLeft()).times(this._containerSize.x / bounds.width); return point.minus(
bounds.getTopLeft()
).times(
this.containerSize.x / bounds.width
);
}, },
pointFromPixel: function(pixel, current) { pointFromPixel: function(pixel, current) {
var bounds = this.getBounds( current ); var bounds = this.getBounds( current );
return pixel.divide(this._containerSize.x / bounds.width).plus(bounds.getTopLeft()); return pixel.divide(
this.containerSize.x / bounds.width
).plus(
bounds.getTopLeft()
);
} }
}; };