After Effects Expression Sammlung

[The Javascript Handbook]

Die Programmiersprache der Expressions in AE basiert auf ExtendScript, eine Variante von JavaScript.

Hier ein Handbuch für tieferes Verständnis

[True Universal Expressions]

In anderen Sprachen haben alle Effekte leider andere Namen, Expressions funktionieren dann leider nicht mehr. Beispielsweise wenn man ein deutsches AE Projekt im Englischen AE öffnet. Um dieses Problem zu umgehen braucht man "True Universal Expressions". Hierzu ersetzt man den Effekteigenschaftennamen mit dem EigenschaftenIndex und gibt dem Effekt Objekt einen benutzerdefinierten Namen (also benennt es um).

Wenn man mit dem Pick-Whip und gedrückter ALT-Taste auf Effekte verlinkt erhält man direkt den Index. Beispielsweise heißt es dann nicht mehr "Schieberegler" sondern "ADBE Slider Control-0001".

[Sample Image Expression]

Bspw. einsetzbar um die Deckkraft einer Ebene anhand einer anderen Ebenen zu steuern:

SampleSize = [10,10];
target = thisComp.layer("Ebene die ausgelesen werden soll");
samplePos = [target.width,target.height]/2;
rgb = target.sampleImage(samplePos, sampleSize, true, time);
hsl = rgbToHsl(rgb);
hsl[2]*100

[Array]

[x] oder [x,y] oder [x,y,z]

Am Beispiel:

carPos = thisComp.layer(„WIGGLE_CAR“).effect(„Wiggle“)(„Schieberegler“);
[value[0], value[1] + carPos];

Wenn die Dimensionen der Eigenschaft „Position“ nicht getrennt werden dürfen, die x und y werte jedoch trotzdem gesondert behandelt werden sollen, benutzt man die obere Expression.

carPos = *Pickwhip zu einem Schieberegler* carPos ist eine Variable, die durch den Wert des Schiebereglers definiert wird.

[value[0], value[1] + carPos]; Steht für den x-Wert und den y-Wert (in diesem Fall y + Wert des Schieberegler)

[Delay]

offset = -.05;
p = thisComp.layer(„Körper_DRAG“);
t = time + offset;
p.position.valueAtTime(t);

Diese Expression wird in einer Eigenschaft eingetippt, die einer anderen Eigenschaft mit einer gewissen Verzögerung folgen soll.

offset = -.05; Die Zeitliche Verschiebung, also - 0,5 Sekunden.

p = thisComp.layer(„Körper_DRAG“); Die „parent“ Ebene. In diesem Fall ein Nullobjekt „Körper_DRAG“, welches sich entlang der y-Achse bewegt und anhängende Objekt - z.B. den Kopf - „hinterherziehen“ soll. Also Pickwhip zum Parent-Objekt

t = time + offset; Die jetzige Zeit minus die Zeitverschiebung.

p.position.valueAtTime(t); Wert der parent-Eigenschaft zur jetzigen Zeit minus einer halben Sekunde

[Weltkoordinaten]

L = thisComp.layer(„Null 1“);
L.toWorld(L.anchorPoint);

Diese Expression wird genutzt, um die „Weltkoordinaten“ einer Verbundenen Ebene zu erhalten. Wenn ein Nullobjekt der Position einer anderen Ebene folgt, kann man kein weiteres Objekt mehr an dessen x / y Position hängen, da diese Werte sich nicht verändern.

Deshalb ist es sinnvoll die Weltkoordniaten mit dieser Expression auslesen zu lassen.

Bedeutet: Die Expression wird in die Position des zu folgenden Objektes eingetippt.

L = *Pickwhip zu einem Nullobjekt etc.*;
L.toWorld(L.anchorPoint);

Fertig.

[If, Else, Or, And Statement]

// Variation A (If Statement: standard if statement)
if (value < 1) { 1 }
else { value }
// Variation B (Else If: extra condition for the if statement)
if (value <= 1) { 0 }
else if (value > 1) { 2 }
else { 1 }
// Variation C (OR Statement: if either requirements are met)
if ( (value < 3) || (value > 1) ) { 2 }
else { value }
// Variation D (AND Statement: if both requirements are met)
if ( (value < 1) && (value > 0) ) { 1 }
else { value }

Das If / Else Statement wird benötigt, wenn komplexere, oder auch weniger komplexe Zusammenhänge programmiert werden müssen.

Beispiel: Das If / else Statemente wird in die Eigenschaft „Deckkraft“ engetippt. Hier muss zunächst eine Variable definidert werden: also v = Skalierung eines Objektes.

if (v > 80) {0} Wenn die Skalierung des verbundenen Objektes den Wert 80 überschreitet, passiert etwas. In diesem Beispiel wird dann die Deckkraft gleich null gesetzt.

else{100} Für jeden anderen Fall, also wenn die Skalierung den Wert 80 nicht überschreitet, passiert etwas anderes. In diesem Beispiel wird die Deckkraft auf 100 gesetz

[Loop]

loopOut(„modifier“);
loopIn („modifier“); cycle / pingpong / offset

Bei der Loop-expression unterscheidet man zunächst zwischen den Eigenschaften „LoopOut“ und „LoopIn“. Die „loopOut“ Eigenschaft wiederholt gesetzte Keyframes in die positive Zeitrichtung, also alles was nach ebendiesen Keyframes kommt. Vorher bewegt sich nichts.

Die „loopIn“ Eigenschaft wiederholt die Keyframes in der Zeit vor diesen Keyframes. Der Loop hört also nach den Keyframes auf.

Des Weiteren gibt es noch die verschiedenen Arten des Loops: Cycle, Pingpong, Offset.

[Loop in UND out]

if (time >= key(1).time){ if (time > key(2).time) loopOut('continue') else value;
}else{ if (time < key(1).time) loopIn('continue'); }

Falls in beide Richtungen, also vor und hinter den Keyframes geloopt werden soll

[Loop für einen Pfad]

valueAtTime(time % key(numKeys).time)

Da bei animierten Pfaden die normale Loop Expression nicht funktioniert.

[Trigger-Expression für Unterkompositionen]

trigger = (Eindimensionaler Wert, z.B. x-Position einer Kamera);
if (trigger >= 2160){
t = time;
while (t >= thisComp.frameDuration){
t -= thisComp.frameDuration;
if (trigger.valueAtTime(t) < 2160){
break;
}
}
time - t;
}else
0

Diese sehr spezifische Expression dient dazu, eine Unterkomposition „zu starten“, wenn ein gewünschter Wert eine bestimmte Größe erreicht. Sie wird benötigt, wenn man ein modulares Projekt anlegt, bei dem das Timing variabel ist. Sie wird auf die „Zeitverzerrung“-Eigenschaft einer Unterkomposition angewandt.

Hat man z.B. eine Kamera in seinem Projekt, die sich entlang der x-Achse bewegt und an verschiedenen Unterkompositionen anhält, um dort eine Animation zu zeigen, müsste man die Unterkompositionen jedes Mal an die richtige Stelle in der Timeline ziehen, wenn sich das Timing der Kamera verändert. Benutzt man jedoch diese Expression, ist das Timing der Unterkoposition abhänging von der x-Position der Kamera. Die Unterkomposition startet also erst, wenn die Kamera bei x = 1080 ankommt.

[Winkel aus einer Bewegung]

Link zum vollen Tutorial

Diese Expression passt die Drehung eines Objektes stets der Bewegung entlang des Motionpath an.

fps = thisComp.frameDuration;
p1 = thisLayer.position.valueAtTime(time-fps);
p2 = thisLayer.position.valueAtTime(time+fps);
delta = sub(p1, p2);
angle = Math.atan2(delta[1], delta[0]);
ang = radians_to_degrees(angle);
(ang)%360;

Erläuterungen zu den einzelnen Code-Zeilen:

  • fps = thisComp.frameDuration; = Variable für die Framerate
  • p1 = thisLayer.position.valueAtTime(time-fps) = Variable für den Zeitpunkt einen Frame vor der momentanen Zeit
  • p2 = thisLayer.position.valueAtTime(time+fps) =Variable für den Zeitpunkt einen Frame nach der momentanen Zeit
  • delta = sub(p1, p2) = erstellt das delta der beiden Koordinaten
  • angle = Math.atan2(delta[1], delta[0]); = komplexer After Effects Kram
  • ang = radians_to_degrees(angle); = Konvertiert den radialen Wert in einen Winkelwert 
  • (ang)%360; = Noch mehr komplexer After Effects Kram

Formebene anhand von Text skalieren

Um die Größe einer Formebene anhand eines Textes anzupassen kann folgender Code verwendet werden.

/*Diesen Schnipsel in die Größeeinstellung des Pfades kopieren*/
s=thisComp.layer("<Name der Textebene>");
w=s.sourceRectAtTime().width+50;
h=s.sourceRectAtTime().height+50;
[w,h]
  • Zeile 1 -> hier den Namen der Textebene angeben auf den sich die Form beziehen soll
  • Zeile 2 + 3 -> Damit die Form nicht am Text "klebt" kann man hier den Abstand vom Text zum Rahmen variieren
/*Diesen Schnipsel in die Positionseinstellungen des Pfades kopieren*/
s=thisComp.layer("<Name der Textebene>");
w=s.sourceRectAtTime().width/2;
h=s.sourceRectAtTime().height/2;
l=s.sourceRectAtTime().left;
t=s.sourceRectAtTime().top;
[w+l,h+t]
  • Zeile 1 -> auch hier muss wieder der enstprechenden Textebene eingegeben werden