Il presente documento spiega le differenze di sintassi del linguaggio delle espressioni tra i motori di espressioni JavaScript e Legacy ExtendScript in After Effects 16.0.

Consulta questo documento per scoprire come migliorare le espressioni per il motore di espressioni JavaScript oppure durante la risoluzione di errori che si verificano quando non è possibile valutare nel motore di espressioni JavaScript le espressioni scritte per versioni precedenti di After Effects.

Il linguaggio delle espressioni in After Effects è basato su JavaScript, che è un’implementazione di ECMAScript. Il motore di espressioni JavaScript in After Effects 16.0 è basato su ECMAScript 2018. Il motore di espressioni Legacy ExtendScript è basato su ECMAScript 3 (1999). (Adobe ExtendScript è inoltre il linguaggio utilizzato per lo scripting in After Effects e altre applicazioni Adobe.)

Puoi seguire gli esempi forniti di seguito, come anche le indicazioni su come creare espressioni che funzionino nei motori di espressioni JavaScript e Legacy ExtendScript.

Le differenze principali tra i motori di espressioni JavaScript e Legacy ExtendScript sono:

Sintassi moderna di JavaScript: miglioramenti apportati al linguaggio delle espressioni

Le espressioni possono utilizzare la sintassi di JavaScript da ECMAScript 2018

Sono state apportate molte aggiunte al linguaggio di JavaScript da ECMAScript 3. Sono presenti nuovi metodi, più compatti e leggibili, da utilizzare con stringhe, matrici e oggetti. Sono inoltre presenti nuovi modi di dichiarare variabili e funzioni, così come parametri predefiniti, operatori spread e altro. Il presente documento non tratta tali modifiche, in quanto si tratta di modifiche generali al linguaggio di JavaScript. Risorse per scoprire di più sulle molte aggiunte alla sintassi sono disponibili ai seguenti collegamenti:

Ulteriori risorse consigliate e approfondite per imparare a usare JavaScript:

.value non è più necessario quando si effettua il collegamento ad altre proprietà da Testo sorgente

Se si fa riferimento a un altro valore di proprietà da una proprietà Testo sorgente, il motore Legacy ExtendScript richiede che .value venga aggiunto al termine della proprietà. Il motore JavaScript mostra il valore della proprietà per impostazione predefinita a meno che non venga utilizzato esplicitamente un altro attributo come .propertyIndex o .name.

Ad esempio:

thisComp.layer("Solid 1").transform.position
 
// In the Legacy engine, this evaluates to "[object Property]" when applied to a Source Text property.
// In the JavaScript engine, this evaluates to the value of the Position property of layer "Solid 1" when applied to a Source Text property.

Blocco di valori proprietà con posterizeTime(0)

In After Effects 16.0, posterizeTime(0) blocca il valore proprietà al tempo 0 nella composizione. Ciò si applica a entrambi i motori JavaScript e Legacy ExtendScript.

Nota:

Non presenta compatibilità retroattiva e può causare risultati inattesi nelle versioni di After Effects precedenti alla 16.0.

Sintassi legacy non compatibile

Quasi tutta la sintassi delle espressioni dal motore di espressioni Legacy ExtendScript è compatibile con il motore di espressioni JavaScript delle versioni successive. Tuttavia, alcuni tipi di sintassi legacy non sono compatibili con il motore di espressioni JavaScript. A volte ciò è causato da modifiche della sintassi nell’attuale JavaScript. In altri casi, la sintassi obsoleta o superata è stata rimossa. Più avanti vengono forniti esempi di sintassi funzionante e non funzionante.

La maggior parte di tali differenze di sintassi può essere corretta mediante lo scripting di un’applicazione che riscrive le espressioni.

Differenze di sintassi if...else

In generale, si consiglia di scrivere sempre le dichiarazioni if...else con interruzioni di riga e parentesi in base alle linee guida MDN. Il motore Legacy ExtendScript tollerava la sintassi flessibile nelle dichiarazioni if...else, tuttavia il motore JavaScript è più rigoroso. Se si utilizza il motore JavaScript, si verifica un errore di valutazione per le sintassi if...else errate.

Non è consentito terminare un’espressione con una dichiarazione if senza un else

Se un’espressione termina con una dichiarazione if senza una dichiarazione else, sarà impossibile per il motore JavaScript valutare l’espressione e si verifica un errore di tipo “Valore non definito usato nell’espressione, potrebbe trattarsi di un indice di matrice fuori gamma”. Nel motore Legacy ExtendScript, la seguente espressione viene valutata con 100 se il tempo è maggiore di 1 secondo, altrimenti con 50:

var x = 50;
if ( time > 1 ) {
    x = 100
}
// The "else" here is implied but not stated.

Per il motore JavaScript è necessario che la parte else della dichiarazione venga dichiarata esplicitamente se è l’ultima nell’espressione:

var x = 50;
if ( time > 1 ) {
    x = 100;
} else {
    x;
}

Ciò consentirà la valutazione corretta sia nel motore JavaScript sia nel motore Legacy ExtendScript.

if ed else non possono trovarsi sulla stessa riga senza parentesi

Una frase if...else su una singola riga senza parentesi viene valutata nel motore Legacy ExtendScript ma non nel motore JavaScript, generando un errore di tipo “Errore di sintassi: token else inatteso” o “Valore non definito usato nell’espressione, potrebbe trattarsi di un indice di matrice fuori gamma”. L’errore varia, a seconda del contesto e del tipo di proprietà.

Nel motore Legacy ExtendScript, la seguente espressione viene valutata con 100 se il tempo è maggiore di 1 secondo, altrimenti con 50:

if ( time > 1 ) 100 else 50;

Il motore JavaScript richiede interruzioni di riga o parentesi per valutare le frasi if...else. Per i casi semplici, è possibile utilizzare invece l’operatore ternario. È possibile utilizzare una qualsiasi delle sintassi seguenti con il motore JavaScript:

// Solution A: adding a line break before "else" will allow both engines to evaluate correctly.
 
if ( time > 1 ) 100
else 50;
 
// Solution B: adding correct bracketing will also allow both engines to evaluate correctly.
 
if ( time > 1 ) { 100 } else { 50 };
 
// Solution C: Use a ternary operator in place of the if...else statement, which also evaluates correctly in both engines.
 
time > 1 ? 100 : 50;

Tutte le soluzioni precedenti vengono valutate correttamente sia nel motore JavaScript sia nel motore Legacy ExtendScript.

Le espressioni non possono terminare con una dichiarazione di funzione

Se un’espressione termina con una dichiarazione di funzione, per il motore JavaScript non è possibile valutare l’espressione e si verifica un errore di tipo “È stato trovato un oggetto di tipo in una posizione in cui è necessario un numero, una matrice o una proprietà”. Nel motore JavaScript, l’ultimo elemento valutato deve restituire un valore, piuttosto che dichiararne uno.

L’esempio seguente funziona nel motore Legacy ma non nel motore JavaScript:

timesTen( value );  // The Legacy engine evaluates this line, even though the function is declared below.
 
function timesTen ( val ) {
    return val * 10
}

Se una funzione viene richiamata come ultima riga (al posto della dichiarazione), l’espressione verrà valutata correttamente in entrambi i motori:

function timesTen ( val ) {
    return val * 10
}
 
timesTen( value );  // The JavaScript engine needs the function call to happen below the declaration in order to return the correct value.

La sintassi breve this() non è consentita; utilizza piuttosto thisLayer()

Nel motore Legacy ExtendScript era consentito l’utilizzo di this come forma breve di thisLayer. Nel motore JavaScript, this si riferisce all’oggetto globale e al suo posto deve essere utilizzato thisLayer. L’utilizzo di this nel motore JavaScript provocherà di solito un errore di tipo “this non è una funzione”.

Nel seguente esempio di Legacy ExtendScript, this viene utilizzato per creare un collegamento compatto a una proprietà Posizione livello testo dalla proprietà Testo sorgente:

this(5)(2).value;

Nel motore JavaScript, this deve essere sostituito da thisLayer:

thisLayer(5)(2).value;

L’utilizzo di thisLayer è compatibile con entrambi i motori di espressioni.

L’accesso ai caratteri dell’indice matrice della proprietà Testo sorgente richiede .value

Nel motore di espressioni Legacy ExtendScript, è possibile accedere ai caratteri di una proprietà del testo con una notazione a parentesi come una matrice:

text.sourceText[0]      // Returns the first character of the Source Text property's text value.

Nel motore JavaScript, è necessario aggiungere .value per accedere ai caratteri:

text.sourceText.value[0]    // Returns the first character of the Source Text property's text value.

Tale sintassi è compatibile con entrambi i motori.

Le proprietà e i metodi snake_case non sono consentiti

Le proprietà e i metodi snake_case obsoleti (scritti con un trattino basso invece della notazione camelCase) non sono supportati dal motore JavaScript. Al loro posto devono essere utilizzate le versioni camelCase, poiché sono compatibili con entrambi i motori. Il seguente è un elenco di proprietà e metodi snake_case obsoleti e delle corrispondenti versioni camelCase.

Proprietà snake_case Proprietà camelCase Metodi snake_case Metodi camelCase

this_comp

this_layer

this_property

color_depth

has_parent

in_point

out_point

start_time

has_video

has_audio

audio_active

anchor_point

audio_levels

time_remap

casts_shadows

light_transmission

accepts_shadows

accepts_lights

frame_duration

shutter_angle

shutter_phase

num_layers

pixel_aspect

point_of_interest

depth_of_field

focus_distance

blur_level

cone_angle

cone_feather

shadow_darkness

shadow_diffusion

active_camera

thisComp

thisLayer

thisProperty

colorDepth

hasParent

inPoint

outPoint

startTime

hasVideo

hasAudio

audioActive

anchorPoint

audioLevels

timeRemap

castsShadows

lightTransmission

acceptsShadows

acceptsLights

frameDuration

shutterAngle

shutterPhase

numLayers

pixelAspect

pointOfInterest

depthOfField

focusDistance

blurLevel

coneAngle

coneFeather

shadowDarkness

shadowDiffusion

activeCamera

value_at_time()

velocity_at_time()

speed_at_time()

nearest_key()

posterize_time()

look_at()

seed_random()

gauss_random()

ease_in()

ease_out()

rgb_to_hsl()

hsl_to_rgb()

degrees_to_radians()

radians_to_degrees()

from_comp_to_surface()

to_comp_vec()

from_comp_vec()

to_world_vec()

from_world_vec()

to_comp()

from_comp()

to_world()

from_world()

temporal_wiggle()

loop_in_duration()

loop_out_duration()

loop_in()

loop_out()

valueAtTime()

velocityAtTime()

speedAtTime()

nearestKey()

posterizeTime()

lookAt()

seedRandom()

gaussRandom()

easeIn()

easeOut()

rgbToHsl()

hslToRgb()

degreesToRadians()

radiansToDegrees()

fromCompToSurface()

toCompVec()

fromCompVec()

toWorldVec()

fromWorldVec()

toComp()

fromComp()

toWorld()

fromWorld()

temporalWiggle()

loopInDuration()

loopOutDuration()

loopIn()

loopOut()

Utilizzo di eval() con espressioni in codifica binaria (.jsxbin)

Le espressioni codificate nel formato binario di ExtendScript (salvato come file .jsxbin binario dal ToolKit CC di ExtendScript) non sono supportate dal motore JavaScript.

Per offuscare un’espressione, utilizza il motore Legacy ExtendScript o un metodo di offuscamento diverso compatibile con ECMAScript 2018. Alcuni metodi di offuscamento possono non essere compatibili con entrambi i motori di espressioni.

Supporto limitato per l’oggetto $. (Dollaro)

I metodi e le proprietà dell’oggetto $. (Dollaro) sono specifici a ExtendScript e prevalentemente non supportati nel motore JavaScript. La presente tabella elenca gli utilizzi supportati e non supportati dell’oggetto $. (Dollaro):

$. non supportato $. supportato

$.fileName

$.hiResTimes

$.stack

$.evalFile()

$.list()

$.setenv()

$.getenv()

$.appEncoding

$.buildDate

$.decimalPoint

$.dictionary

$.error

$.flags

$.includePath

$.level

$.line

$.locale

$.localize

$.memCache

$.os

$.screens

$.strict

$.version

$.build

$.engineName (non supportato nel motore Legacy ExtendScript)

$.global

Nessun supporto per ...reflect.properties, ...reflect.methods e toSource()

reflect.properties e reflect.methods non sono supportati nel motore JavaScript; si tratta di metodi specifici per ExtendScript che non hanno alcun equivalente diretto in JavaScript.

toSource() in JavaScript è ora obsoleto e non fa parte di alcuna traccia standard.

Per visualizzare un elenco delle proprietà e dei metodi disponibili per qualsiasi proprietà di After Effects simile a quanto fornito dai metodi precedenti, utilizza la seguente espressione su una proprietà Testo sorgente e collegala alla proprietà desiderata, ad esempio utilizzando il selettore al posto di thisProperty alla riga 1:

let obj = thisProperty;     // Replace "thisProperty" with a property-link to your desired property.
let props = [];
 
do {
    Object.getOwnPropertyNames(obj).forEach(prop => {
        if (props.indexOf(prop) === -1) {
            props.push(prop);
        }
    });
} while (obj = Object.getPrototypeOf(obj));
 
props.join("\n");           // Returns an array of strings listing the properties and methods available.

L’espressione precedente non è compatibile con il motore Legacy ExtendScript. Utilizza sintassi e metodi non disponibili in ECMAScript 3.

Requisiti di sintassi per le librerie di espressioni .jsx ed eval() con il motore JavaScript

Se si utilizzano le espressioni in una libreria di funzioni di espressione .jsx o se un’espressione viene richiamata in eval(), è necessario modificare alcuni tipi di sintassi:

Deve essere aggiunto un prefisso esplicito per thisLayer. o thisProperty. a qualsiasi metodo o attributo nativo che non sia richiamato esplicitamente su un livello o una proprietà. Il prefisso indica al motore JavaScript su quale oggetto si sta richiamando il metodo o l’attributo.

Le operazioni matematiche sui valori di matrice come la Posizione devono essere calcolati utilizzando matematica vettoriale oppure funzioni cicliche per agire su ogni elemento nella matrice. Gli operatori matematici sovraccaricati come posizione + [100,100] non potranno essere valutati.

Se si utilizza il motore JavaScript, le espressioni vengono pre-elaborate prima della valutazione così da rendere leggibile parte della sintassi per le espressioni Legacy ExtendScript per il nuovo motore. Tuttavia, queste attività di pre-elaborazione non vengono eseguite se si valutano espressioni da una libreria di funzioni di espressione .jsx o se un’espressione viene richiamata all’interno di eval(). In questi casi è necessario apportare manualmente queste modifiche della sintassi. Tutte queste modifiche della sintassi presentano compatibilità retroattiva con il motore Legacy ExtendScript, cosicché una libreria di espressioni .jsx scritta per funzionare con il motore JavaScript funzionerà anche con il motore Legacy ExtendScript.

Consiglio sulle prestazioni: a causa della mancanza di pre-elaborazione, il richiamo di espressioni complesse da una libreria .jsx con questa sintassi e il motore JavaScript può comportare un miglioramento delle prestazioni rispetto al richiamo della stessa espressione direttamente su una proprietà.

Prefisso esplicito di metodi e attributi nativi con thisLayer. o thisProperty.

Nella tabella seguente sono elencati i metodi e gli attributi che richiedono un prefisso. Per esempio, time deve essere scritto thisLayer.time, mentre wiggle() deve essere scritto thisProperty.wiggle()

Questi prefissi sono richiesti solo nei casi in cui l’attributo o il metodo non siano già esplicitamente richiamati su un altro livello o proprietà. Ad esempio, se si richiama thisComp.layer(1).hasParent, l’aggiunta di thisLayer. non è richiesta poiché .hasParent è già richiamato esplicitamente su layer(1).

Metodi che richiedono thisLayer. Attributi che richiedono thisLayer. Metodi che richiedono thisProperty. Attributi che richiedono thisProperty.
comp()
footage()
posterizeTime()
add()
sub()
mul()
div()
clamp()
length()
dot()
normalize()
cross()
lookAt()
timeToFrames()
framesToTime()
timeToTimecode()
timeToFeetAndFrames()
timeToNTSCTimecode()
timeToCurrentFormat()
seedRandom()
random()
gaussRandom()
noise()
degreesToRadians()
radiansToDegrees()
linear()
ease()
easeIn()
easeOut()
rgbToHsl()
hslToRgb()
hexToRgb()
mask()
sourceRectAtTime()
sourceTime()
sampleImage()
toComp()
fromComp()
toWorld()
fromWorld()
toCompVec()
fromCompVec()
toWorldVec()
fromWorldVec()
fromCompToSurface()
time
source
thisProject
colorDepth
transform
anchorPoint
position
scale
rotation
opacity
orientation
rotationX
rotationY
rotationZ
lightTransmission
castsShadows
acceptsShadows
acceptsLights
ambient
diffuse
specular
specularIntensity
shininess
specularShininess
metal
audioLevels
timeRemap
marker
name
width
height
index
parent
hasParent
inPoint
outPoint
startTime
hasVideo
hasAudio
active
enabled
audioActive
cameraOption
pointOfInterest
zoom
depthOfField
focusDistance
aperature
blurLevel
irisShape
irisRotation
irisRoundness
irisAspectRatio
irisDiffractionFringe
highlightGain
highlightThreshold
highlightSaturation
lightOption
intensity
color
coneAngle
coneFeather
shadowDarkness
shadowDiffusion
valueAtTime()
velocityAtTime()
speedAtTime()
wiggle()
temporalWiggle()
smooth()
loopIn()
loopOut()
loopInDuration()
loopOutDuration()
key()
nearestKey()
propertyGroup()
points()
inTangents()
outTangents()
isClosed()
pointsOnPath()
tangentOnPath()
normalOnPath()
createPath()

velocity
speed
numKeys
propertyIndex

Sostituzione degli operatori matematici con funzioni matematiche vettoriali

Entrambi i motori Legacy ExtendScript e JavaScript consentono il sovraccarico degli operatori matematici per le matrici tramite l’utilizzo di sintassi come position + [100.100] ma ciò non funziona per espressioni in una libreria di funzioni di espressione .jsx o all’interno di eval().

Per eseguire operazioni matematiche sulle proprietà di matrice come Posizione, Scala, ecc., è necessario utilizzare gli equivalenti della matematica vettoriale per addizione, sottrazione, moltiplicazione e divisione. Le funzioni di matematica vettoriale funzioneranno inoltre per i numeri regolari, cosicché una funzione che può essere richiamata su proprietà di qualsiasi tipo di dati deve utilizzare le funzioni matematiche vettoriali.

Nota:

Il prefisso thisLayer. deve essere utilizzato con le funzioni matematiche vettoriali.

  • Addizione: thisLayer.add(vec1, vec2)
  • Sottrazione: thisLayer.sub(vec1, vec2)
  • Moltiplicazione: thisLayer.mul(vec, amount)
  • Divisione: thisLayer.div(vec, amount)

Di seguito sono elencati alcuni esempi di espressioni che utilizzano matematica standard e matematica vettoriale aggiornata. Le espressioni matematiche vettoriali utilizzano inoltre il prefisso thisLayer. o thisProperty. appropriato se necessario.

Per trovare la differenza tra un wiggle() e il valore di una proprietà Posizione:

// Standard Math:
wiggle() - value;
 
 
// Vector Math:
thisLayer.sub( thisProperty.wiggle(), value );

Per interpolare tra due valori, simili a linear() ma con un intervallo esteso oltre il minimo e il massimo definiti:

// Standard Math:
value1 + ( ( t - tMin ) / ( tMax - tMin ) ) * ( value2 - value1 );
 
 
// Vector Math:
thisLayer.add( value1, thisLayer.mul( thisLayer.div( thisLayer.sub( t, tMin ), thisLayer.sub( tMax, tMin ) ), thisLayer.sub( value2, value1 ) ) );

Per attivare o interrompere la ciclicità della proprietà Posizione:

// Standard Math:
loopIn( "cycle" ) + loopOut( "cycle" ) - value;
 
 
// Vector Math:
thisLayer.sub( thisLayer.add( thisProperty.loopIn( "cycle" ), thisProperty.loopOut( "cycle" ) ), value );

Questo prodotto è concesso in licenza in base alla licenza di Attribuzione-Non commerciale-Condividi allo stesso modo 3.0 Unported di Creative Commons.  I post su Twitter™ e Facebook non sono coperti dai termini di Creative Commons.

Note legali   |   Informativa sulla privacy online