Exponential Scaling
Posted: March 27th, 2006, 3:19 am
...credit for this script is due to Aaron Fisher on creative cow, who posted it in response to the question of whether there was an easier way to do exponential scaling of objects when you either did not have the option to handle them as 3d objects (or didn't want the render hit), and when you want to avoid the tedious use of the "exponential scale" keyframe assistant.
I am using it for pan/zoom type effects on photos, and it allows me to work faster as you just set two or more keyframes for scale and the expression handles the interpolation of scale between them so that scaling looks like 'zooming' properly (options are linear, ease, easIn or easeOut)
There can be four versions of this script just by changing the one line which determines the interpolation (see comments). I have not modified the script otherwise, except in adding those comments which I just added myself as I worked my way through it, not being an expert scripter myself.
//
/* checking if there are at least two keys; and
if the last key's time value is greater than current time; and
if we are presently at or later than the first key */
if (num_keys >1 && key(num_keys).time > time && key(1).time <= time){
// set var k to be the index of the nearest key; then
k = nearest_key(time).index;
// if that nearest key is less or equal to present time
if (key(k).time <= time) {
// set var a to that value
a = k;
} else {
// otherwise set var a to that value -1
// so: a will always be the value of the key to the left of present position
a = k-1;
}
// and b will always be the value of the key to the right of present position
b= a+1;
/* next four lines set a_val and b_val
to the first array value for each of the keys in which
we are presently between (i.e. the x value);
and a_time and b_time to the time values for those keys*/
a_val = key(a)[0];
b_val = key(b)[0];
a_time = key(a).time;
b_time = key(b).time;
// quick corrections if the a or b values happen to be zero
if(a_val == 0) {
a_val = .1;
}
if (b_val == 0) {
b_val = .1;
}
/* now the real math occurs here; options are:
linear, ease, easeIn, easeOut -- see second line:*/
x = Math.log(b_val) / Math.log(a_val);
exp = linear(time, a_time, b_time, 1, x);
val = Math.pow(a_val, exp);
[val, val];
}else{
value;
}
I am using it for pan/zoom type effects on photos, and it allows me to work faster as you just set two or more keyframes for scale and the expression handles the interpolation of scale between them so that scaling looks like 'zooming' properly (options are linear, ease, easIn or easeOut)
There can be four versions of this script just by changing the one line which determines the interpolation (see comments). I have not modified the script otherwise, except in adding those comments which I just added myself as I worked my way through it, not being an expert scripter myself.
//
/* checking if there are at least two keys; and
if the last key's time value is greater than current time; and
if we are presently at or later than the first key */
if (num_keys >1 && key(num_keys).time > time && key(1).time <= time){
// set var k to be the index of the nearest key; then
k = nearest_key(time).index;
// if that nearest key is less or equal to present time
if (key(k).time <= time) {
// set var a to that value
a = k;
} else {
// otherwise set var a to that value -1
// so: a will always be the value of the key to the left of present position
a = k-1;
}
// and b will always be the value of the key to the right of present position
b= a+1;
/* next four lines set a_val and b_val
to the first array value for each of the keys in which
we are presently between (i.e. the x value);
and a_time and b_time to the time values for those keys*/
a_val = key(a)[0];
b_val = key(b)[0];
a_time = key(a).time;
b_time = key(b).time;
// quick corrections if the a or b values happen to be zero
if(a_val == 0) {
a_val = .1;
}
if (b_val == 0) {
b_val = .1;
}
/* now the real math occurs here; options are:
linear, ease, easeIn, easeOut -- see second line:*/
x = Math.log(b_val) / Math.log(a_val);
exp = linear(time, a_time, b_time, 1, x);
val = Math.pow(a_val, exp);
[val, val];
}else{
value;
}