ADOBE AFTER EFFECTS: Forum Expressions Tutorials Creative Cloud

Dynamically positioning text at 4 existing keyframes, based on its size.

COW Forums : Adobe After Effects Expressions

<< PREVIOUS   •   FAQ   •   VIEW ALL   •   PRINT   •   NEXT >>
Waldemar Werbel
Dynamically positioning text at 4 existing keyframes, based on its size.
on Nov 16, 2017 at 7:54:09 am

Hello all.

I may be way off with my approach here, but I'm wondering whether this is possible... ( I'm not too worried about Y values here, it's the X values that I'm interested in. I'm guessing that the layer.sourceRectAtTime expression will have a part to play here. I'm using the most recent version of AE.)

Let's say I have a single line of text that's justified left and I'd like it to start just off-screen at the first keyframe, come in with its left edge to rest at a given X point between keyframes 2 and 3 and then move off to an X position at keyframe 4 that puts its left edge just beyond the length of the text layer by 10 pixels or so. Attached are some images to illustrate.





I'm thinking that using existing keyframes would allow me to retain the easing parameters of those keyframes?

Thanks for any help you can offer!

Wal.

http://www.wrbl.tumblr.com


Return to posts index

Waldemar Werbel
Re: Dynamically positioning text at 4 existing keyframes, based on its size.
on Nov 16, 2017 at 10:27:01 pm

Okay,

Initial thinking about how this could work was far too muddled and unlikely to ever work...

I found one of Dan's old expressions on using markers to control camera position here: https://forums.creativecow.net/thread/227/17024

and modified it a bit to change the position of my text layer based on the marker name. So far so good - I can change the length of the string of text and it'll always position itself just off screen to begin with.

My question now is - rather than the text layer jumping/snapping to its new position when hitting a marker, is there a way of animating the text layer (a linear animation with an ease) to travel from it's current position to the new..?

Apologies if I'm still barking up the wrong tree and asking a dumb question..!

As ever, thanks for any help.

Wal.

textWidth = thisComp.layer("SAMPLE TEXT").sourceRectAtTime().width;

firstPos = [0-textWidth,800];
onscreenPos = [200,800];
lastPos = [200+textWidth+10,800];

C = thisComp;
n = 0;
if (C.marker.numKeys > 0){
n = C.marker.nearestKey(time).index;
if (C.marker.key(n).time > time){
n--;
}
}
if (n > 0){
if (C.marker.key(n).comment.toLowerCase() == "first"){
firstPos;
}else if(C.marker.key(n).comment.toLowerCase() == "onscreen"){
onscreenPos;
}else if(C.marker.key(n).comment.toLowerCase() == "last"){
lastPos;
}else{
value;
}
}else{
value;
}



http://www.wrbl.tumblr.com


Return to posts index

Dan Ebberts
Re: Dynamically positioning text at 4 existing keyframes, based on its size.
on Nov 17, 2017 at 4:59:31 am

You could, for example replace the line where it snaps to the onscreen position:

onScreenPos;

with something like this:

linear(time,marker.key(n).time,marker.key(n).time+.2,firstPos,onScreenPos);

and do something similar for the last position.


Dan



Return to posts index


Waldemar Werbel
Re: Dynamically positioning text at 4 existing keyframes, based on its size.
on Nov 17, 2017 at 9:31:20 pm

Hi Dan,

As ever, thanks a million for your help - as far as I'm concerned you're without doubt the most useful guy on the internet..!

👍

I'm probably not using it correctly, but that snippet above didn't seem to work - the error returned was 'The property has no keyframe number 1'.

Anyway, after a bit of button mashing I finally got something which is workable (for my needs) - code below.

Another couple of questions, if I may.

As you can see, I'm referencing specific frames to get the animation to happen - the markers aren't doing the triggering, the expression's just using them to see what it needs to do via the 'if' and 'else' statements, which makes me think do I even need the markers any more? If the expression can be written to make a series of positional changes between pairs of frames, then that would be a more efficient approach...

The second question relates to easing via the expression. I'm aware of Penner's equations after coming across another one of your posts - I'm many leagues out of my depth here, but out of interest - any pointers on how you'd begin to implement these into a format that the ease command can access..?

All the best.

Wal.

textWidth = thisComp.layer("SAMPLE TEXT").sourceRectAtTime().width;

firstPos = [0-textWidth,800];
onscreenPos = [200,800];
lastPos = [200+textWidth+10,800];

C = thisComp;
n = 0;
if (C.marker.numKeys > 0){
n = C.marker.nearestKey(time).index;
if (C.marker.key(n).time > time){
n--;
}
}
if (n > 0){
if (C.marker.key(n).comment.toLowerCase() == "first"){
easeOut(time,framesToTime(0),framesToTime(30), firstPos, onscreenPos)
}else if(C.marker.key(n).comment.toLowerCase() == "onscreen"){
onscreenPos;
}else if(C.marker.key(n).comment.toLowerCase() == "last"){
easeIn(time,framesToTime(70),framesToTime(100), onscreenPos, lastPos)
}else{
value;
}
}else{
value;
}


http://www.wrbl.tumblr.com


Return to posts index

Dan Ebberts
Re: Dynamically positioning text at 4 existing keyframes, based on its size.
on Nov 17, 2017 at 10:04:07 pm

Sorry, I didn't catch that those were comp markers. It should have been like this:

linear(time,C.marker.key(n).time,C.marker.key(n).time+.2,firstPos,onScreenPos);


If you know the specific frames where you want the transitions to happen, you could ditch the marker code, it just makes it a little more tedious to adjust things if you need to make changes.

You can't get the built-in eases to use other ease code (you'd have to create your own ease function for that), but you can apply the eases multiple times if you need a more severe ease.


Dan



Return to posts index

Waldemar Werbel
Re: Dynamically positioning text at 4 existing keyframes, based on its size.
on Nov 18, 2017 at 1:02:15 am

Hi Dan,

>but you can apply the eases multiple times if you need a more severe ease.

Do you mean like this?

https://forums.creativecow.net/thread/2/1038950#1056176

I can't work out for sure what going on in there - I did have a go at 'stacking' the eases, but no joy as yet..!

Wal.


Return to posts index


Dan Ebberts
Re: Dynamically positioning text at 4 existing keyframes, based on its size.
on Nov 18, 2017 at 4:13:21 am

>Do you mean like this?


Yes, exactly. You generate a temporary ease and save the value in a variable, then ease that value again to compound the ease and generate the final result (or another intermediate value).

Dan



Return to posts index

Waldemar Werbel
Re: Dynamically positioning text at 4 existing keyframes, based on its size.
on Nov 18, 2017 at 12:12:59 pm

Hi Dan,

Heh, well - I've tied myself up in knots with this one - the theory of it seems straightforward enough, but I can't seem to get it to work properly, or rather, consistently - when it seems to work, there's no discernable (to me!) rhyme nor reason as to why it does..!

New code is below - I've set the easeA variable up a few lines in and then call it later on. The last two numbers in the variable (0 and 30) were eventual guesses, but these values are the only way that I can get it to 'work' - changing that last 30 has the same effect as changing the second 30, which is essentially setting the out point of the ease.

When I try to use something similar (easeB variable) for the easeIn later on nothing happens at all..!

I'm almost definitely going about this in entirely the wrong way - anyone got any pointers to how to properly implement a stacked ease via an expression..?

Thanks again for the help guys!

Wal.

textWidth = thisComp.layer("SAMPLE TEXT").sourceRectAtTime().width;

firstPos = [0-textWidth,800];
onscreenPos = [200,800];
lastPos = [200+textWidth+10,800];

easeA = easeOut(time, 0, 30, 0, 30);
easeB = easeIn(time, 70, 100, 0, 100);

C = thisComp;
n = 0;
if (C.marker.numKeys > 0){
n = C.marker.nearestKey(time).index;
if (C.marker.key(n).time > time){
n--;
}
}
if (n > 0){
if (C.marker.key(n).comment.toLowerCase() == "first"){
easeOut(easeA, framesToTime(0),framesToTime(30), firstPos, onscreenPos);
}else if(C.marker.key(n).comment.toLowerCase() == "onscreen"){
onscreenPos;
}else if(C.marker.key(n).comment.toLowerCase() == "last"){
easeIn(easeB, framesToTime(70), framesToTime(100), onscreenPos, lastPos)
}else{
value;
}
}else{
value;
}


http://www.wrbl.tumblr.com


Return to posts index

Dan Ebberts
Re: Dynamically positioning text at 4 existing keyframes, based on its size.
on Nov 18, 2017 at 4:05:23 pm

I haven't tested this at all, but I think it would need to be more like this:



textWidth = thisComp.layer("SAMPLE TEXT").sourceRectAtTime().width;

firstPos = [0-textWidth,800];
onscreenPos = [200,800];
lastPos = [200+textWidth+10,800];

easeA = easeOut(time, framesToTime(0), framesToTime(30), 0, 100);
easeB = easeIn(time, framesToTime(70), framesToTime(100), 0, 100);

C = thisComp;
n = 0;
if (C.marker.numKeys > 0){
n = C.marker.nearestKey(time).index;
if (C.marker.key(n).time > time){
n--;
}
}
if (n > 0){
if (C.marker.key(n).comment.toLowerCase() == "first"){
easeOut(easeA, 0,100, firstPos, onscreenPos);
}else if(C.marker.key(n).comment.toLowerCase() == "onscreen"){
onscreenPos;
}else if(C.marker.key(n).comment.toLowerCase() == "last"){
easeIn(easeB, 0, 100, onscreenPos, lastPos)
}else{
value;
}
}else{
value;
}



Dan



Return to posts index


Waldemar Werbel
Re: Dynamically positioning text at 4 existing keyframes, based on its size.
on Nov 18, 2017 at 4:21:52 pm

Cheers Dan,

That works insofar as the animation isn't broken, but there's no discernable difference between the eases (ie. stacked ease looks exactly the same as the standard ease...)

Will keep looking at and thinking about it (and post any progress) thanks for your help so far.

Wal.

http://www.wrbl.tumblr.com


Return to posts index

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