このドキュメントでは、After Effects 16.0 の JavaScript エクスプレッションエンジンと以前の ExtendScript エクスプレッションエンジンのエクスプレッション言語の構文の違いについて説明します。

JavaScript エクスプレッションエンジンのエクスプレッションの改善方法について学習したり、After Effects の以前のリリース用に記述したエクスプレッションが JavaScript エクスプレッションエンジンの評価で失敗した際に発生したエラーを修正する場合に、このドキュメントを参照してください。

After Effects のエクスプレッション言語は、JavaScript(ECMAScript の実装)に基づいています。After Effects 16.0 の JavaScript エクスプレッションエンジンは、ECMAScript 2018 に基づいています。以前の ExtendScript エクスプレッションエンジンは、ECMAScript 3(1999)に基づいています(Adobe ExtendScript は、After Effects およびその他の Adobe アプリケーションのスクリプトに使用される言語でもあります)。

後述の例や、JavaScript および以前の ExtendScript の両方のエクスプレッションエンジンで機能するエクスプレッションの作成方法のガイダンスに従うことができます。

JavaScript と以前の ExtendScript のエクスプレッションエンジンの構文の主な違いを次に示します。

最新の JavaScript 構文:エクスプレッション言語に対しておこなわれた改善

エクスプレッションで ECMAScript 2018 の JavaScript 構文を使用できる

ECMAScript 3 以降、JavaScript 言語に多くの追加がおこなわれています。文字列、配列およびオブジェクトと共に使用する、よりコンパクトで読み取り可能な新しいメソッドがあります。また、変数や関数、デフォルトパラメーター、スプレッド演算子などを宣言するための新しい方法もあります。これらの変更は、JavaScript 言語に対する一般的なものなので、このドキュメントでは扱いません。多くの構文の追加に関する学習リソースへのリンクを次に示します。

JavaScript について学習するための、その他の詳細な推奨リソース:

Source Text から他のプロパティにリンクする場合に .value が不要に

Source Text プロパティから他のプロパティ値を参照する場合、以前の ExtendScript エンジンでは、.value をプロパティの末尾に追加する必要があります。JavaScript エンジンは、.propertyIndex.name などの他の属性が明示的に使用されない限り、デフォルトでプロパティの値を表示します。

例えば、次のようになります。

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.

posterizeTime(0) のプロパティ値のフリーズ

After Effects 16.0 では、posterizeTime(0) は、コンポジションの時間 0 でプロパティ値をフリーズします。これは、JavaScript と以前の ExtendScript エンジンの両方に適用されます。

注意:

これは下位互換ではなく、16.0 より前のバージョンの After Effects で予期しない結果になる可能性があります。

互換性のない以前の構文

以前の ExtendScript エクスプレッションエンジンからのほとんどすべてのエクスプレッション構文は、JavaScript エクスプレッションエンジンと上位互換性があります。ただし、一部の以前の構文は、JavaScript エクスプレッションエンジンと互換性がありません。これは、最新の JavaScript での構文の変更による場合があります。他には、旧バージョンの構文や古い構文が削除された場合もあります。機能しない構文および機能する構文の例を次に示します。

これらの構文の違いのほとんどは、エクスプレッションを書き直すアプリケーションスクリプトで修正できます。

if...else 構文の違い

一般に、if...else ステートメントは、MDN ガイドラインに従って、常に改行および括弧と共に記述することをお勧めします。以前の ExtendScript エンジンは if...else ステートメントの厳密でない構文に対して耐性がありましたが、JavaScript エンジンは厳密です。正しくない if...else 構文は、JavaScript エンジンを使用した場合の評価に失敗します。

else を含まない if ステートメントで終わるエクスプレッションは許可されない

エクスプレッションが else ステートメントを含まない if ステートメントで終わる場合、JavaScript エンジンは、エラー「未定義の値がエクスプレッションで使用されています (配列の添え字が範囲外である可能性があります)」で、エクスプレッションの評価に失敗します。以前の ExtendScript エンジンでは、次のエクスプレッションは、time が 1 秒より大きい場合は 100 と評価され、その他の場合は 50 と評価されます。

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

JavaScript エンジンでは、エクスプレッションの最後のステートメントの場合、ステートメントの else 部分が明示的に記述される必要があります。

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

これは、JavaScript エンジンおよび以前の ExtendScript エンジンの両方で正しく評価されます。

if および else を括弧なしで同じ行にできない

単一の行の括弧のない if...else ステートメントは、以前の ExtendScript エンジンでは評価されますが、JavaScript エンジンでは、「構文エラー : 予期しないトークン else」または「未定義の値がエクスプレッションで使用されています (配列の添え字が範囲外である可能性があります)」というエラーで評価に失敗します。エラーは、コンテキストおよびプロパティタイプによって異なります。

以前の ExtendScript エンジンでは、次のエクスプレッションは、time が 1 秒より大きい場合は 100 と評価され、その他の場合は 50 と評価されます。

if ( time > 1 ) 100 else 50;

JavaScript エンジンでは、if...else ステートメントを評価するには、改行または括弧が必要です。単純な場合は、代わりに三項演算子が使用されることがあります。次の構文はいずれも 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;

このすべてのソリューションは、JavaScript エンジンおよび以前の ExtendScript エンジンの両方で正しく評価されます。

エクスプレッションを関数宣言で終了できない

エクスプレッションが関数宣言で終了する場合、JavaScript エンジンは、エラー「タイプのオブジェクトが、Number、Array、または Property が必要な場所で見つかりました」で、エクスプレッションの評価に失敗します。JavaScript エンジンでは、評価された最後のアイテムは、宣言するのではなく、値を返す必要があります。

次の例は、以前のエンジンでは機能しますが、JavaScript エンジンでは機能しません。

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

最後の行で(宣言の代わりに)関数が呼び出される場合、エクスプレッションは両方のエンジンで正しく評価されます。

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.

this() 省略形構文は許可されず、代わりに thisLayer() が使用される

以前の ExtendScript エンジンでは、これは、thisLayer の省略形として使用できました。JavaScript エンジンでは、これはグローバルオブジェクトを参照するので、代わりに thisLayer を使用する必要があります。JavaScript エンジンでこれを使用すると、通常、「これは関数ではありません」というエラーが表示されます。

次の以前の ExtendScript の例では、これを使用して Source Text プロパティから Text Layer Position プロパティへのコンパクトリンクを作成します。

this(5)(2).value;

JavaScript エンジンでは、これは thisLayer に置き換える必要があります。

thisLayer(5)(2).value;

thisLayer の使用は、両方のエクスプレッションエンジンと互換性があります。

Source Text プロパティの文字への配列インデックスアクセスには .value が必要

以前の ExtendScript エクスプレッションエンジンでは、text プロパティの文字は、配列のような括弧表記でアクセスできました。

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

JavaScript エンジンでは、文字にアクセスするために .value を追加する必要があります。

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

この構文は、両方のエンジンと互換性があります。

スネークケースのプロパティおよびメソッドは許可されない

廃止されたスネークケースのプロパティおよびメソッド(キャメルケースの代わりにアンダースコアを使用して記述)は、JavaScript エンジンではサポートされません。両方のエンジンと互換性があるので、代わりにキャメルケースバージョンを使用する必要があります。次に、廃止されたスネークケースおよび対応するキャメルケースのリストを示します。

スネークケースのプロパティ キャメルケースのプロパティ スネークケースのメソッド キャメルケースのメソッド

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

バイナリエンコードされた(.jsxbin)エクスプレッションでの eval() の使用

ExtendScript バイナリ形式でエンコード(ExtendScript ToolKit CC からバイナリ .jsxbin ファイルで保存)されたエクスプレッションは、JavaScript エンジンではサポートされません。

エクスプレッションを難読化したい場合は、以前の ExtendScript エンジンを使用するか、ECMAScript 2018 と互換性のある別の難読化メソッドを使用します。一部の難読化メソッドは、両方のエクスプレッションエンジンと互換性がない可能性があります。

$.(ドル)オブジェクトの制限付きサポート

$.(ドル)オブジェクトメソッドおよびプロパティは、ExtendScript 専用で、JavaScript エンジンではほとんどサポートされません。次の表に、使用がサポートされない $.(ドル)オブジェクトとサポートされるオブジェクトを示します。

サポートされない $. サポートされる $.

$.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(これは以前の ExtendScript エンジンではサポートされません)

$.global

...reflect.properties、...reflect.methods および toSource() のサポートなし

reflect.properties および reflect.methods は、JavaScript エンジンではサポートされません。JavaScript には同等の指示がない、ExtendScript 専用のメソッドです。

JavaScript の toSource() は廃止され、標準化過程には含まれません。

前述のメソッドで提供されたものと同様の所定の After Effects プロパティについて、使用可能なプロパティおよびメソッドのリストを確認するには、次の Source Text プロパティのエクスプレッションを使用して、目的のプロパティにリンクします(例えば、1 行目の thisProperty の代わりにピックウイップを使用します)。

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.

このエクスプレッションは、以前の ExtendScript エンジンとは互換性がありません。ECMAScript 3 で使用できない構文およびメソッドを使用します。

JavaScript エンジンでの .jsx エクスプレッションライブラリおよび eval() の構文要件

.jsx エクスプレッション関数ライブラリ内でエクスプレッションを使用する場合、または eval() 内からエクスプレッションが呼び出される場合、特定の構文を修正する必要があります。

明示的な thisLayer. または thisProperty. プレフィックスを、レイヤーまたはプロパティで明示的に呼び出されないネイティブのメソッドまたは属性に追加する必要があります。このプレフィックスは、呼び出しているメソッドまたは属性がどのオブジェクトのものかを JavaScript エンジンに指示します。

Position のような配列の値の演算操作は、配列の各アイテムに作用させるために、ベクトル演算を使用するか、ループ関数を使用して計算する必要があります。position + [100,100] のようなオーバーロードされた演算操作は、評価されません。

JavaScript エンジンを使用する場合、エクスプレッションは、一部の以前の ExtendScript エクスプレッション構文を新しいエンジンで読み取れるようにするために、評価前に事前処理されます。ただし、これらの事前処理タスクは、.jsx エクスプレッション関数ライブラリからエクスプレッションを評価する場合、またはエクスプレッションが eval() 内で呼び出される場合は、実行されません。この場合、前述の構文の修正は手動でおこなう必要があります。これらすべての構文の修正は、以前の ExtendScript エンジンと下位互換性があるので、JavaScript エンジンで機能するように記述された .jsx エクスプレッションライブラリも、以前の ExtendScript エンジンで機能します。

パフォーマンスのヒント:事前処理がおこなわれないことにより、この構文および JavaScript エンジンを使用した .jsx ライブラリからの複雑なエクスプレッションの呼び出しは、同じエクスプレッションをプロパティで直接呼び出すのに比べて、パフォーマンスが向上したように見えることがあります。

thisLayer. または thisProperty. を使用するネイティブのメソッドおよび属性に明示的にプレフィックスを付ける

次の表に、プレフィックスが必要なメソッドおよび属性を示します。例えば、time が thisLayer.time と記述される必要があるのに対して、wiggle()thisProperty.wiggle() と記述される必要があります。

これらのプレフィックスは、属性またはメソッドが他のレイヤーまたはプロパティでまだ明示的に呼び出されていない場合にのみ必要です。例えば、thisComp.layer(1).hasParent を呼び出す場合、thisLayer. は不要です(.hasParentlayer(1) で既に明示的に呼び出されているので)。

thisLayer. を必要とするメソッド thisLayer. を必要とする属性 thisProperty. を必要とするメソッド 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

演算操作のベクトル演算関数への置き換え

JavaScript と以前の ExtendScript エンジンのどちらも、position + [100,100] のような構文を使用すると、配列の演算操作をオーバーロードできますが、これは、.jsx エクスプレッション関数ライブラリ内または eval() 内のエクスプレッションでは機能しません。

Position、Scale などの配列プロパティで演算を実行するには、加算、減算、乗算、除算に、ベクトル演算と同等のものを使用する必要があります。また、ベクトル演算関数は、整数に対して機能するので、どちらかのデータタイプのプロパティで呼び出される可能性のある関数は、ベクトル演算関数を使用する必要があります。

注意:

ベクトル演算関数には、thisLayer. プレフィックスを使用する必要があります。

  • 可算:thisLayer.add(vec1, vec2)
  • 減算:thisLayer.sub(vec1, vec2)
  • 乗算:thisLayer.mul(vec, amount)
  • 除算:thisLayer.div(vec, amount)

次に、標準的な演算および更新されたベクトル演算を使用するエクスプレッションの例を示します。また、ベクトル演算エクスプレッションでは、必要に応じて、適切な thisLayer. または thisProperty. プレフィックスを使用します。

wiggle() と Position プロパティの値の違いを見つけるには:

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

linear() と同様に 2 つの値を補間するが、定義された最小および最大値を超えて範囲を拡張するには:

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

Position プロパティ内外をループするには:

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

本作品は Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License によってライセンス許可を受けています。  Twitter™ および Facebook の投稿には、Creative Commons の規約内容は適用されません。

法律上の注意   |   プライバシーポリシー