mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-25 22:56:11 +03:00
Merge pull request #631 from openseadragon/spring
Now animating zoom spring exponentially
This commit is contained in:
commit
b92d3f36a8
@ -56,6 +56,7 @@ OPENSEADRAGON CHANGELOG
|
|||||||
* Fixed an issue with zero size viewers in IE8 (#609)
|
* Fixed an issue with zero size viewers in IE8 (#609)
|
||||||
* Fixed: Cross Origin policy not working (#613)
|
* Fixed: Cross Origin policy not working (#613)
|
||||||
* Optimized tile loading by clearing the queue on a re-draw when imageLoaderLimit is set (#616)
|
* Optimized tile loading by clearing the queue on a re-draw when imageLoaderLimit is set (#616)
|
||||||
|
* Now animating zoom spring exponentially (#631)
|
||||||
|
|
||||||
1.2.1:
|
1.2.1:
|
||||||
|
|
||||||
|
@ -38,10 +38,14 @@
|
|||||||
* @class Spring
|
* @class Spring
|
||||||
* @memberof OpenSeadragon
|
* @memberof OpenSeadragon
|
||||||
* @param {Object} options - Spring configuration settings.
|
* @param {Object} options - Spring configuration settings.
|
||||||
* @param {Number} options.initial - Initial value of spring, default to 0 so
|
* @param {Number} options.springStiffness - Spring stiffness. Must be greater than zero.
|
||||||
* spring is not in motion initally by default.
|
* The closer to zero, the closer to linear animation.
|
||||||
* @param {Number} options.springStiffness - Spring stiffness.
|
* @param {Number} options.animationTime - Animation duration per spring, in seconds.
|
||||||
* @param {Number} options.animationTime - Animation duration per spring.
|
* Must be greater than zero.
|
||||||
|
* @param {Number} [options.initial=0] - Initial value of spring.
|
||||||
|
* @param {Boolean} [options.exponential=false] - Whether this spring represents
|
||||||
|
* an exponential scale (such as zoom) and should be animated accordingly. Note that
|
||||||
|
* exponential springs must have non-zero values.
|
||||||
*/
|
*/
|
||||||
$.Spring = function( options ) {
|
$.Spring = function( options ) {
|
||||||
var args = arguments;
|
var args = arguments;
|
||||||
@ -52,7 +56,7 @@ $.Spring = function( options ) {
|
|||||||
options = {
|
options = {
|
||||||
initial: args.length && typeof ( args[ 0 ] ) == "number" ?
|
initial: args.length && typeof ( args[ 0 ] ) == "number" ?
|
||||||
args[ 0 ] :
|
args[ 0 ] :
|
||||||
0,
|
undefined,
|
||||||
/**
|
/**
|
||||||
* Spring stiffness.
|
* Spring stiffness.
|
||||||
* @member {Number} springStiffness
|
* @member {Number} springStiffness
|
||||||
@ -72,6 +76,17 @@ $.Spring = function( options ) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$.console.assert(typeof options.springStiffness === "number" && options.springStiffness !== 0,
|
||||||
|
"[OpenSeadragon.Spring] options.springStiffness must be a non-zero number");
|
||||||
|
|
||||||
|
$.console.assert(typeof options.animationTime === "number" && options.springStiffness !== 0,
|
||||||
|
"[OpenSeadragon.Spring] options.animationTime must be a non-zero number");
|
||||||
|
|
||||||
|
if (options.exponential) {
|
||||||
|
this._exponential = true;
|
||||||
|
delete options.exponential;
|
||||||
|
}
|
||||||
|
|
||||||
$.extend( true, this, options);
|
$.extend( true, this, options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,10 +98,13 @@ $.Spring = function( options ) {
|
|||||||
this.current = {
|
this.current = {
|
||||||
value: typeof ( this.initial ) == "number" ?
|
value: typeof ( this.initial ) == "number" ?
|
||||||
this.initial :
|
this.initial :
|
||||||
0,
|
(this._exponential ? 0 : 1),
|
||||||
time: $.now() // always work in milliseconds
|
time: $.now() // always work in milliseconds
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$.console.assert(!this._exponential || this.current.value !== 0,
|
||||||
|
"[OpenSeadragon.Spring] value must be non-zero for exponential springs");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @member {Object} start
|
* @member {Object} start
|
||||||
* @memberof OpenSeadragon.Spring#
|
* @memberof OpenSeadragon.Spring#
|
||||||
@ -108,6 +126,12 @@ $.Spring = function( options ) {
|
|||||||
value: this.current.value,
|
value: this.current.value,
|
||||||
time: this.current.time
|
time: this.current.time
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (this._exponential) {
|
||||||
|
this.start._logValue = Math.log(this.start.value);
|
||||||
|
this.target._logValue = Math.log(this.target.value);
|
||||||
|
this.current._logValue = Math.log(this.current.value);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$.Spring.prototype = /** @lends OpenSeadragon.Spring.prototype */{
|
$.Spring.prototype = /** @lends OpenSeadragon.Spring.prototype */{
|
||||||
@ -117,8 +141,17 @@ $.Spring.prototype = /** @lends OpenSeadragon.Spring.prototype */{
|
|||||||
* @param {Number} target
|
* @param {Number} target
|
||||||
*/
|
*/
|
||||||
resetTo: function( target ) {
|
resetTo: function( target ) {
|
||||||
|
$.console.assert(!this._exponential || target !== 0,
|
||||||
|
"[OpenSeadragon.Spring.resetTo] target must be non-zero for exponential springs");
|
||||||
|
|
||||||
this.start.value = this.target.value = this.current.value = target;
|
this.start.value = this.target.value = this.current.value = target;
|
||||||
this.start.time = this.target.time = this.current.time = $.now();
|
this.start.time = this.target.time = this.current.time = $.now();
|
||||||
|
|
||||||
|
if (this._exponential) {
|
||||||
|
this.start._logValue = Math.log(this.start.value);
|
||||||
|
this.target._logValue = Math.log(this.target.value);
|
||||||
|
this.current._logValue = Math.log(this.current.value);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -126,10 +159,18 @@ $.Spring.prototype = /** @lends OpenSeadragon.Spring.prototype */{
|
|||||||
* @param {Number} target
|
* @param {Number} target
|
||||||
*/
|
*/
|
||||||
springTo: function( target ) {
|
springTo: function( target ) {
|
||||||
|
$.console.assert(!this._exponential || target !== 0,
|
||||||
|
"[OpenSeadragon.Spring.springTo] target must be non-zero for exponential springs");
|
||||||
|
|
||||||
this.start.value = this.current.value;
|
this.start.value = this.current.value;
|
||||||
this.start.time = this.current.time;
|
this.start.time = this.current.time;
|
||||||
this.target.value = target;
|
this.target.value = target;
|
||||||
this.target.time = this.start.time + 1000 * this.animationTime;
|
this.target.time = this.start.time + 1000 * this.animationTime;
|
||||||
|
|
||||||
|
if (this._exponential) {
|
||||||
|
this.start._logValue = Math.log(this.start.value);
|
||||||
|
this.target._logValue = Math.log(this.target.value);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -139,6 +180,27 @@ $.Spring.prototype = /** @lends OpenSeadragon.Spring.prototype */{
|
|||||||
shiftBy: function( delta ) {
|
shiftBy: function( delta ) {
|
||||||
this.start.value += delta;
|
this.start.value += delta;
|
||||||
this.target.value += delta;
|
this.target.value += delta;
|
||||||
|
|
||||||
|
if (this._exponential) {
|
||||||
|
$.console.assert(this.target.value !== 0 && this.start.value !== 0,
|
||||||
|
"[OpenSeadragon.Spring.shiftBy] spring value must be non-zero for exponential springs");
|
||||||
|
|
||||||
|
this.start._logValue = Math.log(this.start.value);
|
||||||
|
this.target._logValue = Math.log(this.target.value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setExponential: function(value) {
|
||||||
|
this._exponential = value;
|
||||||
|
|
||||||
|
if (this._exponential) {
|
||||||
|
$.console.assert(this.current.value !== 0 && this.target.value !== 0 && this.start.value !== 0,
|
||||||
|
"[OpenSeadragon.Spring.setExponential] spring value must be non-zero for exponential springs");
|
||||||
|
|
||||||
|
this.start._logValue = Math.log(this.start.value);
|
||||||
|
this.target._logValue = Math.log(this.target.value);
|
||||||
|
this.current._logValue = Math.log(this.current.value);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -146,15 +208,31 @@ $.Spring.prototype = /** @lends OpenSeadragon.Spring.prototype */{
|
|||||||
*/
|
*/
|
||||||
update: function() {
|
update: function() {
|
||||||
this.current.time = $.now();
|
this.current.time = $.now();
|
||||||
this.current.value = (this.current.time >= this.target.time) ?
|
|
||||||
this.target.value :
|
var startValue, targetValue;
|
||||||
this.start.value +
|
if (this._exponential) {
|
||||||
( this.target.value - this.start.value ) *
|
startValue = this.start._logValue;
|
||||||
|
targetValue = this.target._logValue;
|
||||||
|
} else {
|
||||||
|
startValue = this.start.value;
|
||||||
|
targetValue = this.target.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentValue = (this.current.time >= this.target.time) ?
|
||||||
|
targetValue :
|
||||||
|
startValue +
|
||||||
|
( targetValue - startValue ) *
|
||||||
transform(
|
transform(
|
||||||
this.springStiffness,
|
this.springStiffness,
|
||||||
( this.current.time - this.start.time ) /
|
( this.current.time - this.start.time ) /
|
||||||
( this.target.time - this.start.time )
|
( this.target.time - this.start.time )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (this._exponential) {
|
||||||
|
this.current.value = Math.exp(currentValue);
|
||||||
|
} else {
|
||||||
|
this.current.value = currentValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -127,6 +127,7 @@ $.Viewport = function( options ) {
|
|||||||
animationTime: this.animationTime
|
animationTime: this.animationTime
|
||||||
});
|
});
|
||||||
this.zoomSpring = new $.Spring({
|
this.zoomSpring = new $.Spring({
|
||||||
|
exponential: true,
|
||||||
initial: 1,
|
initial: 1,
|
||||||
springStiffness: this.springStiffness,
|
springStiffness: this.springStiffness,
|
||||||
animationTime: this.animationTime
|
animationTime: this.animationTime
|
||||||
|
@ -72,6 +72,7 @@
|
|||||||
<script src="/test/modules/tilecache.js"></script>
|
<script src="/test/modules/tilecache.js"></script>
|
||||||
<script src="/test/modules/referencestrip.js"></script>
|
<script src="/test/modules/referencestrip.js"></script>
|
||||||
<script src="/test/modules/tilesourcecollection.js"></script>
|
<script src="/test/modules/tilesourcecollection.js"></script>
|
||||||
|
<script src="/test/modules/spring.js"></script>
|
||||||
<!-- The navigator tests are the slowest (for now; hopefully they can be sped up)
|
<!-- The navigator tests are the slowest (for now; hopefully they can be sped up)
|
||||||
so we put them last. -->
|
so we put them last. -->
|
||||||
<script src="/test/modules/navigator.js"></script>
|
<script src="/test/modules/navigator.js"></script>
|
||||||
|
77
test/modules/spring.js
Normal file
77
test/modules/spring.js
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/* global module, asyncTest, $, ok, equal, notEqual, start, test, Util, testLog, propEqual, console */
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
var originalNow;
|
||||||
|
var now;
|
||||||
|
|
||||||
|
module("spring", {
|
||||||
|
setup: function () {
|
||||||
|
now = 0;
|
||||||
|
originalNow = OpenSeadragon.now;
|
||||||
|
|
||||||
|
OpenSeadragon.now = function() {
|
||||||
|
return now;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
teardown: function () {
|
||||||
|
OpenSeadragon.now = originalNow;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest('regular spring', function() {
|
||||||
|
var spring = new OpenSeadragon.Spring({
|
||||||
|
initial: 5,
|
||||||
|
animationTime: 1,
|
||||||
|
springStiffness: 0.000001
|
||||||
|
});
|
||||||
|
|
||||||
|
equal(spring.current.value, 5, 'initial current value');
|
||||||
|
equal(spring.target.value, 5, 'initial target value');
|
||||||
|
|
||||||
|
spring.springTo(6);
|
||||||
|
equal(spring.current.value, 5, 'current value after springTo');
|
||||||
|
equal(spring.target.value, 6, 'target value after springTo');
|
||||||
|
|
||||||
|
now = 500;
|
||||||
|
spring.update();
|
||||||
|
Util.assessNumericValue(5.5, spring.current.value, 0.00001, 'current value after first update');
|
||||||
|
equal(spring.target.value, 6, 'target value after first update');
|
||||||
|
|
||||||
|
now = 1000;
|
||||||
|
spring.update();
|
||||||
|
equal(spring.current.value, 6, 'current value after second update');
|
||||||
|
equal(spring.target.value, 6, 'target value after second update');
|
||||||
|
|
||||||
|
start();
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest('exponential spring', function() {
|
||||||
|
var spring = new OpenSeadragon.Spring({
|
||||||
|
exponential: true,
|
||||||
|
initial: 1,
|
||||||
|
animationTime: 1,
|
||||||
|
springStiffness: 0.000001
|
||||||
|
});
|
||||||
|
|
||||||
|
equal(spring.current.value, 1, 'initial current value');
|
||||||
|
equal(spring.target.value, 1, 'initial target value');
|
||||||
|
|
||||||
|
spring.springTo(2);
|
||||||
|
equal(spring.current.value, 1, 'current value after springTo');
|
||||||
|
equal(spring.target.value, 2, 'target value after springTo');
|
||||||
|
|
||||||
|
now = 500;
|
||||||
|
spring.update();
|
||||||
|
Util.assessNumericValue(1.41421, spring.current.value, 0.00001, 'current value after first update');
|
||||||
|
equal(spring.target.value, 2, 'target value after first update');
|
||||||
|
|
||||||
|
now = 1000;
|
||||||
|
spring.update();
|
||||||
|
equal(spring.current.value, 2, 'current value after second update');
|
||||||
|
equal(spring.target.value, 2, 'target value after second update');
|
||||||
|
|
||||||
|
start();
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
@ -37,6 +37,7 @@
|
|||||||
<script src="/test/modules/tilecache.js"></script>
|
<script src="/test/modules/tilecache.js"></script>
|
||||||
<script src="/test/modules/referencestrip.js"></script>
|
<script src="/test/modules/referencestrip.js"></script>
|
||||||
<script src="/test/modules/tilesourcecollection.js"></script>
|
<script src="/test/modules/tilesourcecollection.js"></script>
|
||||||
|
<script src="/test/modules/spring.js"></script>
|
||||||
<!-- The navigator tests are the slowest (for now; hopefully they can be sped up)
|
<!-- The navigator tests are the slowest (for now; hopefully they can be sped up)
|
||||||
so we put them last. -->
|
so we put them last. -->
|
||||||
<script src="/test/modules/navigator.js"></script>
|
<script src="/test/modules/navigator.js"></script>
|
||||||
|
Loading…
Reference in New Issue
Block a user