Este documento explica as diferenças de sintaxe da linguagem de expressões entre os mecanismos de expressão Javascript e Legacy ExtendScript no After Effects 16.0.

Consulte este documento para saber mais sobre como melhorar suas expressões para o mecanismo de expressões de Javascript, ou ao corrigir erros que ocorrem quando a avaliação de expressões escritas para versões anteriores do After Effects retorna falhas no mecanismo de expressões de Javascript.

A linguagem de expressões no After Effects tem base em Javascript, que é uma implementação de ECMAScript. O mecanismo de expressões Javascript no After Effects 16.0 tem base em ECMAScript 2018. O mecanismo de expressões Legacy ExtendScript tem base em ECMAScript 3 (1999). (O Adobe ExtendScript também é a linguagem usada na criação de scripts no After Effects e em outros aplicativos da Adobe.)

Você pode seguir os exemplos fornecidos abaixo, além da orientação para a criação de expressões que funcionam em ambos os mecanismos de expressões JavaScript e Legacy ExtendScript.

As diferenças principais entre os mecanismos de expressão Javascript e Legacy ExtendScript são:

Sintaxe moderna do Javascript: melhorias feitas à linguagem de expressões

As expressões podem usar a sintaxe de JavaScript do ECMAScript 2018

Muitas adições foram feitas à linguagem JavaScript desde o ECMAScript 3. Há novos métodos para usar com sequências de caracteres, matrizes e objetos que são mais compactos e legíveis. Também há novas maneiras de declarar variáveis e funções, bem como parâmetros padrão, operadores spread e muito mais. Este documento não aborda essas alterações, porque se aplicam à linguagem JavaScript. Os recursos para saber mais sobre as muitas adições de sintaxe podem ser encontrados nos seguintes links:

Recursos adicionais e detalhados recomendados para saber mais sobre o JavaScript:

.value não é mais necessário ao vincular a outras propriedades a partir do Texto de origem

Ao fazer referência a outro valor de propriedade a partir de uma propriedade de texto de origem, o mecanismo do Legacy ExtendScript requer que .value seja adicionado ao final da propriedade. O mecanismo do JavaScript mostra o valor da propriedade por padrão, a menos que outro atributo como .propertyIndex ou .name seja usado explicitamente.

Por exemplo:

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.

Congelar valores de propriedade com posterizeTime(0)

No After Effects 16.0, posterizeTime(0) congela o valor de propriedade na hora 0 na composição. Isso se aplica aos mecanismos de Javascript e de Legacy ExtendScript.

Observação:

Isso não tem compatibilidade com versões anteriores e pode causar resultados inesperados em versões do After Effects anteriores à 16.0.

Sintaxe herdada incompatível

Praticamente qualquer sintaxe de expressão do mecanismo de expressões do Legacy ExtendScript tem compatibilidade com versões futuras do mecanismo de expressões de Javascript. No entanto, há algumas sintaxes herdadas que não são compatíveis com o mecanismo de expressões de Javascript. Às vezes, isso é causado por alterações de sintaxe no Javascript moderno. Em outros casos, sintaxes obsoletas ou desatualizadas foram removidas. Os exemplos de sintaxes funcionais e não funcionais estão localizados abaixo.

A maioria dessas diferenças de sintaxe pode ser corrigida por meio do script do aplicativo que re-escreve as expressões.

Diferenças da sintaxe if...else

Geralmente, é recomendável escrever sempre instruções if...else com quebras de linhas e colchetes de acordo com as diretrizes MDN. O mecanismo do Legacy ExtendScript costumava tolerar sintaxes amplas em intruções if...else, no entanto, o mecanismo do JavaScript é restrito. A sintaxe de if...else incorreta retorna falha na avaliação ao usar o mecanismo do JavaScript.

Concluir de uma expressão com uma instrução if não é permitido

Quando uma expressão é concluída com uma instrução if sem uma instrução else, o mecanismo do JavaScript falha ao avaliar e retorna o erro “Valor indefinido usado na expressão (pode ser um subscript fora do intervalo da matriz?)”. No mecanismo do Legacy ExtendScript, a seguinte expressão avalia para 100 se o tempo for maior que 1 segundo, caso contrário resulta em 50:

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

O mecanismo JavaScript requer a parte else da instrução para ser exibido explicitamente, caso seja a última instrução na expressão:

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

Isso resultará na avaliação correta em ambos os mecanismos do JavaScript e do Legacy ExtendScript.

If e else não podem estar na mesma linha sem colchetes

Uma instrução if...else em uma única linha sem colchetes avalia no mecanismo do Legacy ExtendScript, mas não avalia no mecanismo do JavaScript e retorna um erro como “Erro de sintaxe: Token inesperado else” ou “Valor indefinido usado na expressão (pode ser um subscript fora do intervalo da matriz?)”. O erro varia, dependendo do tipo de contexto e de propriedade.

No mecanismo do Legacy ExtendScript, a seguinte expressão avalia para 100 se o tempo for maior que 1 segundo, caso contrário resulta em 50:

if ( time > 1 ) 100 else 50;

O mecanismo JavaScript requer quebra de linha ou colchete para avaliar instruções if...else. Para casos simples, o operador ternário pode ser usado. Qualquer uma das seguintes sintaxes pode ser usada com o mecanismo do 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;

Todas as soluções acima avaliam corretamente no mecanismo do JavaScript e no mecanismo do Legacy ExtendScript.

Expressões não podem terminar em uma declaração de função

Se uma expressão é concluída com uma declaração de função, o mecanismo JavaScript não avalia a expressão com o erro “objeto do tipo localizado onde requer um número, uma matriz ou uma propriedade”. No mecanismo do JavaScript, o último item avaliado deve retornar um valor, em vez de declarar um.

Os seguintes exemplos funcionam no mecanismo do Legacy, mas não no mecanismo do JavaScript:

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

Quando uma função é chamada como a última linha (em vez da declaração), a expressão será avaliada corretamente em ambos os mecanismos:

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.

A sintaxe abreviada this() não é permitida; em vez disso, use thisLayer()

No mecanismo do Legacy ExtendScript, this podia ser usado como formato abreviado para thisLayer. No mecanismo do JavaScript, this se refere ao objeto global e thisLayer deve ser usado. Usar this no mecanismo do JavaScript resultará normalmente no erro “this não é uma função”.

No exemplo a seguir do Legacy ExtendScript, this é usado para criar um vínculo compacto a uma propriedade Posição da camada de texto da propriedade Texto de origem:

this(5)(2).value;

No mecanismo do JavaScript, isso deve ser substituído por thisLayer:

thisLayer(5)(2).value;

Usar thisLayer é compatível com ambos os mecanismos de expressão.

O acesso do índice de matrizes da propriedade de Texto de origem a caractere requer .value

No mecanismo de expressão do Legacy ExtendScript, os caracteres de uma propriedade de texto podem ser acessados com anotação entre colchetes como uma matriz:

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

No mecanismo do JavaScript, .value deve ser adicionado para acessar os caracteres:

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

Essa sintaxe é compatível com ambos os mecanismos.

Propriedades e métodos de SnakeCase não são permitidos

As propriedades e os métodos obsoletos do SnakeCase (gravados com um underscore (_) em vez do camelCase) não são suportados pelo mecanismo do JavaScript. Em vez disso, as versões de camelCase devem ser usadas, porque são compatíveis com os dois mecanismos. A seguir está uma lista do SnakeCase obsoleto e o camelCase correspondente.

Propriedades de SnakeCase Propriedades de camelCase Métodos do SnakeCase Métodos do 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()

Uso de eval() com expressões (.jsxbin) binárias

As expressões codificadas no formato binário do ExtendScript (salvas como um arquivo binário. jsxbin do ExtendScript Toolkit CC) não são suportadas pelo mecanismo do JavaScript.

Se você deseja ofuscar uma expressão, use o mecanismo do Legacy ExtendScript ou use um método diferente de ofuscação que seja compatível com o ECMAScript 2018. Alguns métodos de ofuscação podem não ser compatíveis com os dois mecanismos de expressão.

Suporte limitado para o objeto $. (Dólar)

Os métodos e as propriedades do objeto $. (Dólar) são específicos ao ExtendScript e são suportados em maior parte no mecanismo do JavaScript. Esta tabela lista usos não suportadas e suportados do objeto $. (Dólar):

Sem suporte a $. Com suporte a $.

$.fileName

$.hiResTimes

$.stack

$.evalFile()

$.lista()

$.setenv()

$.getenv()

$.appEncoding

$.buildDate

$.decimalPoint

$.dictionary

$.erro

$.flags

$.includePath

$.level

$.linha

$.locale

$.localize

$.memCache

$.os

$.screens

$.strict

$.version

$.build

$.engineName (isso não é suportado no mecanismo do Legacy ExtendScript)

$.global

Não há suporte para ...reflect.properties, ...reflect.methods e toSource()

reflect.propertiesreflect.methods não são suportados no mecanismo do JavaScript; são métodos específicos ao ExtendScript que não têm nenhum equivalente direto no JavaScript.

toSource() no JavaScript foi descontinuado e não faz parte de nenhum monitoramento padrão.

Para exibir uma lista de propriedades e métodos disponíveis para qualquer propriedade específica do After Effects semelhante ao que foi fornecido pelos métodos acima, use a seguinte expressão em uma propriedade de Texto de origem e vincule-a à sua propriedade desejada, por exemplo, usando o ícone de seleção no lugar de thisProperty na linha 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.

A expressão acima não é compatível com o mecanismo do Legacy ExtendScript. Usa a sintaxe e os métodos não disponíveis no ECMAScript 3.

Requisitos de sintaxe para bibliotecas de expressão .jsx e eval() com o mecanismo JavaScript

Ao usar expressões em uma biblioteca de funções de expressões .jsx ou quando uma expressão é chamada de dentro de eval(), determinadas sintaxes precisam ser modificadas:

Um prefixo thisLayer. ou thisProperty. explícito deve ser adicionado a qualquer método ou atributo nativo ou que não é chamado explicitamente uma camada ou propriedade. O prefixo instrui o mecanismo do JavaScript que o objeto está chamando o método ou atributo.

Operações matemáticas em valores de matriz como Posição devem ser calculados usando matemática vetorial ou usando funções de looping para atuar em cada item da matriz. Operadores matemáticos sobrecarregados como posição + [100,100] não avaliarão.

Ao usar o mecanismo JavaScript, as expressões são processadas antes da avaliação para fazer parte da sintaxe de expressões do Legacy ExtendScript legível pelo novo mecanismo. No entanto, essas tarefas de pré-processamento não são executadas ao avaliar expressões de uma biblioteca de funções de expressões .jsx ou quando uma expressão é chamada de dentro de eval(). As modificações acima da sintaxe devem ser feitas manualmente para esses casos. Todas essas modificações da sintaxe são compatíveis com versões anteriores com o mecanismo do Legacy ExtendScript, portanto, uma biblioteca de expressões .jsx escrita para trabalhar com o mecanismo JavaScript também trabalhará com o mecanismo do Legacy ExtendScript.

Dica de desempenho: devido à falta de pré-processamento, chamar expressões complexas de uma biblioteca .jsx com essa sintaxe e o mecanismo do JavaScript, pode resultar em uma melhoria no desempenho, comparado a chamar a mesma expressão diretamente em uma propriedade.

Prefixar explicitamente métodos e atributos nativos com thisLayer. ou thisProperty.

A tabela a seguir lista os métodos e atributos que exigem um prefixo. Por exemplo, o tempo deve ser escrito como thisLayer.time, e wiggle() deve ser escrito como thisProperty.wiggle(). 

Esses prefixos são necessários somente em casos em que o atributo ou método já não está sendo chamado explicitamente em outra camada ou propriedade. Por exemplo, ao chamar thisComp.layer(1).hasParent, adicionar thisLayer. não é obrigatório pois .hasParent já está sendo chamado explicitamente em layer(1).

Métodos que requerem thisLayer. Atributos que requerem thisLayer. Métodos que requerem thisProperty. Atributos que requerem 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

Substituição de operadores matemáticos com funções matemáticas vetoriais

Os mecanismos Javascript e LegacyExtendScript permitem sobrecarga de operadores matemáticos para matrizes usando sintaxes como posição + [100,100], mas isso não funciona para expressões em uma biblioteca de funções de expressão .jsx ou para dentro de eval().

Para executar a matemática em propriedades de matriz como Posição, Escala etc., os equivalentes matemáticos de vetores devem ser usados para adição, subtração, multiplicação e divisão. As funções matemáticas vetoriais também funcionarão para números regulares, portanto uma função que pode ser chamada em propriedades de dados de qualquer um dos dois tipos de dados deve usar as funções matemáticas vetoriais.

Observação:

O prefixo thisLayer. deve ser usado com as funções matemáticas de vetores.

  • Adição: thisLayer.add(vec1, vec2)
  • Subtração: thisLayer.sub(vec1, vec2)
  • Multiplicação: thisLayer.mul(vec, amount)
  • Divisão: thisLayer.div(vec, amount)

Abaixo estão alguns exemplos de expressões usando a matemática padrão e a matemática vetorial atualizada. As expressões matemáticas de vetores também usam os prefixos thisLayer. ou thisProperty. apropriados quando necessário.

Para localizar a diferença entre um wiggle() e o valor de uma propriedade de Posição:

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

Para interpolar entre dois valores, de modo similar a linear(), mas com um intervalo estendido além do mínimo e o máximo definido:

// 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 ) ) );

Para repetir uma propriedade de Posição para dentro e para fora:

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

Esta obra está licenciada sob uma licença não adaptada da Creative Commons Attribution-Noncommercial-Share Alike 3.0  As publicações do Twitter™ e do Facebook não são cobertas pelos termos do Creative Commons.

Avisos legais   |   Política de privacidade online