ADOBE AFTER EFFECTS: Forum Expressions Tutorials Creative Cloud

Text bouncy animation back and forth based on inPoint and outPoint and layer markers

COW Forums : Adobe After Effects Expressions

<< PREVIOUS   •   FAQ   •   VIEW ALL   •   PRINT   •   NEXT >>
Camilla Panebarco
Text bouncy animation back and forth based on inPoint and outPoint and layer markers
on Aug 30, 2017 at 4:23:31 pm

Hello everyone,

I'm trying to create a text animation preset with parameters controlled by sliders, in order to improove our workflow (I've worked with tons of text animation presets, but I always have to reset keyframes and many other stuff so I decided to create my own, eventually!)

Basically, I add a Text Animator and put the script within an Expression Selector; the script takes some param values from the sliders attached to the layer (or a parent controller, if not NULL) and animate the characters with a bouncy animation effect.
From the controllers I can set randomness, character offset, character overlapping and bounce parameters.
The animation starts from the inPoint of the layer and ends at the time of a Layer Marker named "Animation IN".

The script is working ok so far, but I can't go any further.
I would like an expression which reverse animate the text, starting from another Layer Marker ("Animation OUT") and ending at the outPoint of the text layer.
The reverse animation should include the bouncy effect and revert the order of the characters.

Hope my question was clear enough, please tell me if there's something I missed.
Thanks,
Camilla

// parameters
controller = this;
try {
controller = parent;
amp = controller.effect("bounce amp")("Slider");
freq = controller.effect("bounce freq")("Slider");
decay = controller.effect("bounce decay")("Slider");
frameOverlap = controller.effect("frame overlap")("Slider") * thisComp.frameDuration; // convert frames to seconds
charOffset = controller.effect("char offset")("Slider") % textTotal; // force offset to stay in range [0,textTotal]
rand = controller.effect("random")("Checkbox");
seed = controller.effect("random seed")("Slider");
} catch (e) {
controller = this;
amp = controller.effect("bounce amp")("Slider");
freq = controller.effect("bounce freq")("Slider");
decay = controller.effect("bounce decay")("Slider");
frameOverlap = controller.effect("frame overlap")("Slider") * thisComp.frameDuration; // convert frames to seconds
charOffset = controller.effect("char offset")("Slider") % textTotal; // force offset to stay in range [0,textTotal]
rand = controller.effect("random")("Checkbox");
seed = controller.effect("random seed")("Slider");
}

// selector range
startVal = [100, 100, 100];
endVal = [0, 0, 0];

// get markers time to set character animation
// duration, start frame and end frame
inStart = inPoint;
charDuration = 5 * thisComp.frameDuration; // convert frames to seconds
try { charDuration = Math.abs(marker.key("Animation IN").time - inStart) / textTotal; } catch (e) { }
inEnd = inStart + charDuration;

// character interval
interval = charDuration - frameOverlap;
if(interval &lt; 0) interval = 0;

seedRandom(seed,true);
chars = [0];
for(i = 1; i &lt;= textTotal; i++)
{
if(rand != 0) chars[i] = getRandom(1,textTotal + 1,chars);
else chars[i] = i;
}

if(textIndex &lt;= charOffset) offsetIndex = textIndex + textTotal - charOffset;
else offsetIndex = textIndex - charOffset;
t = time - (chars[offsetIndex] - 1) * interval;

if(t &lt;= inEnd) ease(t, inStart, inEnd, startVal, endVal);
else {
amp = linear(amp,0,(endVal - startVal) / inEnd);
w = freq * Math.PI * 2;
if(w != 0) endVal + amp * (Math.sin((t - inEnd) * w) / Math.exp(decay * (t - inEnd)) / w);
}


// functions
function indexOf(array, item)
{
for(i = 0; i &lt; array.length; i++) { if(array[i] == item) return i; }
return -1;
}
function getRandom(min, max, previous)
{
r = Math.floor(random(min,max));
while(indexOf(previous,r) >=0) { r = Math.floor(random(min,max)); }
return r;
}


Return to posts index

Camilla Panebarco
Re: Text bouncy animation back and forth based on inPoint and outPoint and layer markers
on Aug 31, 2017 at 3:49:01 pm

I've written a shorter expression, just to get things more clear.

At this point, the expression animate the text in and out, based on two markers and in/out point:
- animation IN starts at inPoint, ends at first marker
- animation OUT starts at second marker, ends at outPoint
- if no marker is found, animation IN starts at inPoint and ends after 15 frames (set in espression) and animation OUT is not played

I would like to add the bouncy effect after the IN animation and before the OUT animation.

I know how to add it after the IN animation

if(t < end) ease(t, start, end, startVal, endVal);
else {
amp = linear(amp,0,(endVal - startVal) / end);
w = freq * Math.PI * 2;
endVal + amp * (Math.sin((t - end) * w) / Math.exp(decay * (t - end)) / w);
}


But I cannot figure out how to manage the animation OUT bounce (this should be a reverse bounce).

Any help on this would be great!
Thanks!
Camilla

// animation parameters
start = inPoint;
duration = 15 * thisComp.frameDuration;
reverse = false;

// bouncy parameter
amp = 1;
freq = 2;
decay = 5;

// set params based on keys and in/out points
if(marker.numKeys > 0) {
if(marker.nearestKey(time).index == 1) {
duration = Math.abs(marker.nearestKey(time).time - start);
}
else if(marker.nearestKey(time).index == 2) {
start = marker.nearestKey(time).time;
duration = Math.abs(outPoint - start - thisComp.frameDuration);
reverse = true;
}
}

charDuration = duration / textTotal;
end = start + charDuration;

// selector values range
startVal = [100, 100, 100];
endVal = [0, 0, 0];
// current character index
charIndex = textIndex;

if(reverse == true) {
// selector values range
startVal = [0, 0, 0];
endVal = [100, 100, 100];
// current character index
charIndex = textTotal - textIndex + 1;
}
t = time - (charIndex - 1) * charDuration;

ease(t, start, end, startVal, endVal);


Return to posts index

Camilla Panebarco
Re: Text bouncy animation back and forth based on inPoint and outPoint and layer markers
on Sep 1, 2017 at 1:20:02 pm

In the end, I was able to finalize the script! I paste the script for any interested user.

Some instructions:
- create a text layer
- add an animator
- remove the range selector
- add an expression selector
- paste the code below within the Amount property

The text is now animated (ENTER animation only)

IN/OUT POINTS AND MARKERS
The ENTER animation starts at INPOINT. With markers you can set the duration of animation and add an EXIT animation.
Add 1 marker
The ENTER animation starts at INPOINT and ends at marker time
Add 2 markers
The ENTER animation starts at INPOINT and ends at the first marker time
The EXIT animation starts at the second marker time and ends at OUTPOINT

Add whatever property you want to animate (position, scale, rotation and so on) and choose the selector base you like (characters, lines, words)

PARAMETERS
Parameters are set internally, but they can be linked to slider controls for ease of use.
Animation
duration (int, frames) the duration of text animation (total animation excluding bouncy effect)
overlap (int, frames) animation overlap among characters
Index
rand (bool) if true characters are randomly animated
seed (float) random seed
offset (integer) character offset
Bounciness
amp (float) bounciness overshoot
freq bounciness frequency
decay bounciness decay

Hope you enjoy it!
Camilla

// animation parameters
start = inPoint;
reverse = false;

duration = 5 * textTotal * thisComp.frameDuration;
overlap = 0 * thisComp.frameDuration;

// index parameters
rand = true;
seed = 10;
offset = 1 % textTotal;

// bouncy parameter
amp = 2;
freq = 3;
decay = 5;

// set params based on keys and in/out points
if(marker.numKeys > 0) {
if(marker.nearestKey(time).index == 1) {
duration = Math.abs(marker.nearestKey(time).time - start);
}
else if(marker.nearestKey(time).index == 2) {
start = marker.nearestKey(time).time;
duration = Math.abs(outPoint - start - thisComp.frameDuration);
reverse = true;
}
}

// set duration for character animation
charDuration = (duration / textTotal) - overlap;
if(charDuration &lt;= 0) charDuration = thisComp.frameDuration;
end = start + charDuration;

// selector values range
startVal = [100, 100, 100];
endVal = [0, 0, 0];
idx = textIndex;

if(reverse == true) {
// selector values range
startVal = [0, 0, 0];
endVal = [100, 100, 100];
// current character index
idx = textTotal - textIndex + 1;
}

// set character index array
chars = initCharacterArray(textTotal, rand, seed);
// current character index
charIndex = getCurrentIndex(idx, chars, offset);
t = time - (charIndex) * (charDuration);

if(reverse && t &lt;= start) {
amp = linear(amp,0,(startVal - endVal) / charDuration) * amp;
w = freq * Math.PI * 2;
startVal + amp * (Math.sin((start - t) * w) / Math.exp(decay * (start - t)) / w);
}
else if(t &lt;= end) ease(t, start, end, startVal, endVal);
else if(!reverse){
amp = linear(amp,0,(endVal - startVal) / charDuration) * amp;
w = freq * Math.PI * 2;
endVal + amp * (Math.sin((t - end) * w) / Math.exp(decay * (t - end)) / w);
}
else endVal


// functions
// set character index array
function initCharacterArray(tot, rand, seed)
{
characters = [0];
if(rand != 0) seedRandom(seed, true);
for(i = 1; i&lt;= tot; i++) {
if(rand != 0) characters[i] = getRandom(1, tot + 1, characters);
else characters[i] = i;
}
return characters;
}
// get current character index
function getCurrentIndex(idx, chars, offset)
{
tot = chars.length - 1;
if(idx &lt;= offset) offsetIndex = idx + tot - offset;
else offsetIndex = idx - offset;

return chars[offsetIndex - 1];
}
// get index of item in array
function indexOf(array, item)
{
for(i = 0; i &lt; array.length; i++) { if(array[i] == item) return i; }
return -1;
}
// get unique random number between min and max
function getRandom(min, max, previous)
{
r = Math.floor(random(min,max));
while(indexOf(previous,r) >=0) { r = Math.floor(random(min,max)); }
return r;
}


Return to posts index

<< PREVIOUS   •   VIEW ALL   •   PRINT   •   NEXT >>
© 2017 CreativeCOW.net All Rights Reserved
[TOP]