Skip to main content
Inspiring
September 30, 2022
Answered

Using a dropdown expression control to create keyframes

  • September 30, 2022
  • 1 reply
  • 809 views

There are a few different ways to ask this question, which could either clarify or muddy the waters:

- Is there a way to create keyframes using an expression connected to a dropdown menu using an if statement?

OR

- Is there a way to change the actual value of a property using an expression rather than just the value being displayed? (Meaning, if I use an expression to reference 'value' it would actually change as opposed to being what was originally input)

OR

- Is there a way to ease between values of a property controlled by that dropdown?

 

What I'm working on

I'm in the process of creating an effect preset to make boxes whose size is controlled by a dropdown. Because there is a margin between the boxes as well as the boxes and the edges, the sizes aren't necessarily linear in nature. Because of that, I have the sizes connected to a dropdown menu (1/3 width = 565, 1/2 = 885, and so on). What I am hoping to accomplish is to be able to keyframe the sizes in some way without having to manually enter the box size each time and can use the dropdown instead. However, if I add keyframes to the size at the various points I'm hoping to change it and then set the dropdown back to the NULL value so that the expression is just referencing the value, the size doesn't actually change (which makes sense since the entered value hasn't changed between keyframes). If I add keyframes to the dropdown the change is abrubt rather than eased (also makes sense since there isn't values between the dropdown entries). So then, is there a way to add some sort of easing between the values controlled by the dropdown? Even if it involves something like adding another expression controller (slider, et cetera).

This topic has been closed for replies.
Correct answer Dan Ebberts

Suppose your dropdown menu has 3 choices for box size, then you could have an expression like this for shape layer rectangle size

m = thisComp.layer("Controls").effect("Box Size")("Menu");
sizes = [400,565,885];
if (m.numKeys > 1){
  n = m.nearestKey(time).index;
  if (time < m.key(n).time) n--;
  if (n == 0){
    s = sizes[m.key(1).value-1];
  }else if (n == m.numKeys){
    s = sizes[m.key(m.numKeys).value-1];
  }else{
    t1 = m.key(n).time;
    t2 = m.key(n+1).time;
    v1 = sizes[m.key(n).value-1];
    v2 = sizes[m.key(n+1).value-1];
    s = ease(time,t1,t2,v1,v2);
  }
}else
  s = sizes[m-1];
[s,s]

The expression links to the dropdown menu (on layer "Controls" in this example), defines the actual width/height of the box for each menu entry and eases between those sizes if there are multiple keyframes on the menu control. Hopefully you can extract what you need from this example.

1 reply

Mylenium
Legend
September 30, 2022

Expressions can't create anything nor "bake" values into keyframes, so the answer to your first two questions is a thundering "No". The answer to your third question is "Yes, but it's complicated". This is where complicated valueAtTime() calculations with the results piped through linear() and ease() functions come into play. Here's an example provided by Dan Ebberts two weeks ago that has some basics:

 

https://community.adobe.com/t5/after-effects-discussions/keyframes-question-delay-adjustment-by-a-set-number-of-frames/m-p/13206096

 

I misunderstood the user's request, but the principle is pretty much the same. You just would not use the ease times in the code, but rather something like:

 

tStart=key(x-1).time;
tEnd=key(x).time;
mStart=valueAtTime(tStart);
mEnd=valueAtTime(tEnd);

ease(time,tStart,tEnd,mStart,mEnd);

 

This is just a bit of incomplete, simplified code that you could use to replace the other such functions with the necessary adaptations.

 

Mylenium

Inspiring
September 30, 2022

Thank you so much! I had pretty much guessed there wasn't a way to bake in values but figured I would ask to be sure 🙂 

 

I think the information you provided is certainly enough to get me started on a solution. This was honestly more of a 'can I do this...' than a 'I HAVE TO DO THIS' question as I've recently been taking a deeper dive into expressions and making effect presets for things I have to do a lot. I've already saved myself a ton of time by making a rigged box (thank you, Slemmer Creative for this wonderful tool) with a pseudo effect to control a drop shadow. If I have to manually change the size by entering in a number, it's not that big of a deal (I'll just feel cooler if there is a way, ha).

Dan Ebberts
Community Expert
Dan EbbertsCommunity ExpertCorrect answer
Community Expert
September 30, 2022

Suppose your dropdown menu has 3 choices for box size, then you could have an expression like this for shape layer rectangle size

m = thisComp.layer("Controls").effect("Box Size")("Menu");
sizes = [400,565,885];
if (m.numKeys > 1){
  n = m.nearestKey(time).index;
  if (time < m.key(n).time) n--;
  if (n == 0){
    s = sizes[m.key(1).value-1];
  }else if (n == m.numKeys){
    s = sizes[m.key(m.numKeys).value-1];
  }else{
    t1 = m.key(n).time;
    t2 = m.key(n+1).time;
    v1 = sizes[m.key(n).value-1];
    v2 = sizes[m.key(n+1).value-1];
    s = ease(time,t1,t2,v1,v2);
  }
}else
  s = sizes[m-1];
[s,s]

The expression links to the dropdown menu (on layer "Controls" in this example), defines the actual width/height of the box for each menu entry and eases between those sizes if there are multiple keyframes on the menu control. Hopefully you can extract what you need from this example.