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
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).