Adobe After Effects CS5 : Expressions – Using Markers

The expression language gives you access to the attributes of layer (and composition) markers. This can be extremely useful for synchronizing or easily establishing timing relationships between animated events.

The marker attributes that appear most frequently in expressions are time and index. As you might guess, the time attribute represents the time (in seconds) where the marker is located on the timeline. The index attribute represents the marker’s order on the timeline, where 1 represents the left-most marker. You can also retrieve the marker nearest to a time that you specify by using nearestKey(). For example, to access the layer marker nearest to the current comp time use

marker.nearestKey(time)

 

This can be handy, but more often you’ll want to know the most recent previous marker. The code necessary to retrieve it looks like this:

n = 0;
if (marker.numKeys > 0){
   n = marker.nearestKey(time).index;
   if (marker.key(n).time > time){
     n--;
   }
}

Note that this piece of code by itself is not very useful. When you do use it, you’ll always combine it with additional code that makes it suitable for the particular property to which the expression will be applied. Because it’s so versatile and can show up in expressions for virtually any property, it’s worth looking at in detail.

The first line creates a variable, n, and sets its value to 0. If the value is still 0 when the routine finishes, it means that at the current time no marker was reached or that there are no markers on this layer.

The next line, a JavaScript if statement, checks if the layer has at least one marker. If there are no layer markers, After Effects skips to the end of the routine with the variable n still set to 0. You need to make this test because the next line attempts to access the nearest marker with the statement

n = marker.nearestKey(time).index;

If After Effects attempted to execute this statement and there were no layer markers, it would generate an error and the expression would be disabled. It’s best to defend against these kinds of errors so that you can apply the expression first and add the markers later if you want to.

If there is at least one layer marker, the third line of the expression sets n to the index of the nearest marker. Now all you have to do is determine if the nearest marker occurs before or after the current comp time with the statement

if (marker.key(n).time > time){
    n--;
}

This tells After Effects to decrement n by 1 if the nearest marker occurs later than the current time.

The result of all this is that the variable n contains the index of the most recent previous marker or 0 if no marker has yet been reached.

So how can you use this little routine? Consider a simple example.

Trigger Animation at Markers

Say you have a keyframed animation that you want to trigger at various times. All you need to do is drop a layer marker (just press * on the numeric keypad) wherever you want the action to be triggered. Then, apply this expression to the animated property:

n = 0;
if (marker.numKeys > 0){
  n = marker.nearestKey(time).index;
  if (marker.key(n).time > time){
    n--;
  }
}if (n == 0){
  valueAtTime(0);
}else{
  t = time - marker.key(n).time;
  valueAtTime(t)
}

As you can see, it’s the previous marker routine with six new lines at the end. These lines tell After Effects to use the property’s value from time 0 if there are no previous markers. Otherwise, variable t is defined to be the time since the most recent previous marker, and the value for that time is used.

The result of this is that the animation will run, beginning at frame 0, wherever there is a layer marker.

Play Only Frames with Markers

Suppose you want to achieve a stop-motion animation effect by displaying only specific frames of your footage, say playing only the frames when your actor reaches the apex of a jump so he appears to fly or hover.

First enable time remapping for the layer, then scrub through the Timeline and drop a layer marker at each frame that you want to include. Finally, apply this expression to the Time Remap property:

n = marker.numKeys;
if (n > 0){
  f = timeToFrames(time);
  idx = Math.min(f + 1, n);
  marker.key(idx).time
}else{
  value
}

 

In this expression, the variable n stores the total number of markers for the layer. The if statement next checks whether there is at least one marker. If not, the else clause executes, instructing After Effects to run the clip at normal speed. If there are markers, the expression first calculates the current frame using timeToFrames(), which converts whatever time you pass to it into the appropriate frame number. Here, it receives the current comp time and returns the current frame number, which is stored in variable f.

Next you need to convert the current frame number to a corresponding marker index for the frame you actually want to display. It turns out that all you need to do is add 1. That means when the current frame is 0, you actually want to show the frame that is at marker 1. When frame is 1, you want to show the frame at marker 2, and so on. The line

idx = Math.min(f + 1, n);

 

calculates the marker index and stores it in the variable idx. Using Math.min() ensures the expression never tries to access more markers than there are (which would generate an error and disable the expression). Instead, playback freezes on the last frame that has a marker.

Finally, you use the idx variable to retrieve the time of the corresponding marker. This value becomes the result of the expression, which causes After Effects to display the frame corresponding to the marker (Figure 1).

Figure 1. The bottom line in the graph represents how the Time Remap property would behave without the expression. As you would expect, it is a linear, gradual increase. The upper, stair-stepped line is the result of the expression. Because the expression plays only frames with markers (represented in the graph by small triangles), time advances much more quickly.