AfterEffects expression よく使うものまとめ

いいものがあれば追記していきます。

Adobe Expressionの詳細はこちら

https://helpx.adobe.com/jp/after-effects/using/expression-language-reference.html

https://helpx.adobe.com/jp/after-effects/using/expression-basics.html

有志作のリファレンスページ

https://aereference.com/expressions


## 数値系

### 16:9画面内で16:9画像をはみ出さないように回転させるときの倍率

1080pの画面内で1080pの素材を回転するときなど

`203.972886119 %`

ちなみに逆数は
`49.026123963 %`

算出方法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274492/99f51294-dbee-d4c1-70e9-bbded760320c.png)

### ぼよよん推移

0.0…1.0の推移をぼよよんとする関数。
```js:ぼよよん推移
// _time: 時間(推移スタートが0), _transitionDuration: 何秒かけて推移するか
let rate = Math.min(1, _time / _transitionDuration ));
rate==0? 0: rate==1? 1: Math.pow(2, -8 * rate) * Math.sin((rate * 6 - 0.75) * ((2 * Math.PI)/3)) + 1;
```
反動で1.28くらいまでいくので注意。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274492/7cb1cd59-b45a-50b1-f2f3-e7ead031a6f7.png)

このサイトにいろんなイージイーズのjs関数も書いてあって便利すぎる。
https://easings.net/ja#

### positionのlerp

意外と標準装備されてない。

```js:positionのlerp
add(_pos2, mul(sub(_pos1, _pos2), _rate))
```
_pos2（_rateが1のときのposition）から書き始めることに注意。
rateは0.0…1.0だが、それを超えた値でも正常に動きます。
それが嫌なら事前にclampしといてください。

ちなみに浮動小数のclampも無いので置いとくね。
### 数字のclamp
```js:浮動小数のclamp
Math.min(1, Math.max(0, _rate))
```
minの直後に最大値、maxの後に最小値を書くので注意。

## キーフレーム系

### 現在時間の直前のキーフレームを取得する

デフォルトでは、「nearestKey(time)」（一番近くのキーを取得）しか無いので、取得したキーが現在時間の後ろだったら1個前のキーを参照するようにした。

```js:指定時間の直前のキーフレームを取得する
let checkEffect = thisComp.layer("レイヤー").effect("*エフェクト*");
let lastKey = (checkEffect.nearestKey(time).time > time)? checkEffect.key(checkEffect.nearestKey(time).index-1): checkEffect.nearestKey(time);
```

発展形

直前のキーフレームからの経過秒数を取得する。


```js:指定時間の直前のキーフレームを取得する
let checkEffect = thisComp.layer("レイヤー").effect("*エフェクト*");
let lastKey = (checkEffect.nearestKey(time).time > time)? checkEffect.key(checkEffect.nearestKey(time).index-1): checkEffect.nearestKey(time);
let timeFromLastKey = time - lastKey.time;
```

## マーカー系

### マーカーでフェードイン/アウト

コメントを「in」「out」にしたマーカーでフェードイン/アウトする

```js:マーカーでフェードイン/アウト
function fadeInOutWithMarker() {

	nkey = marker.nearestKey(time);

	if (nkey.comment.trim().toUpperCase() == "IN" && time < nkey.time) {
		return (time - inPoint) / (nkey.time - inPoint);
	} else
	if (nkey.comment.trim().toUpperCase() == "OUT" && nkey.time < time) {
		return (outPoint - time) / (outPoint - nkey.time);
	} else {
		return 1;
	}
}

fadeInOutWithMarker() * 100; // 透明度に使うときはx100する
```

### マーカー間の時間レートを取得する
透明度とかでマーカーのタイミングをチェックするときに使う

```js:マーカー間の時間レートを取得する
// 対象のレイヤー
let targetLayer = thisComp.layer("レイヤー名");

let mlist = targetLayer.marker;
if (mlist.numKeys > 0) {
  let nextMarker = null;
  for (let i = 1; i <= mlist.numKeys; i++) {
    let m = mlist.key(i);
    if (m.time > time) {
      nextMarker = m;
      break;
    }
  }
  if (!nextMarker) {
    nextMarker = {time: targetLayer.outPoint, index: mlist.numKeys};
  }

  let lastMarker = nextMarker.index > 1 ? mlist.key(nextMarker.index-1) : {time: 0, index: 0};
  if (!lastMarker) {
    lastMarker = {time: 0, index: 0};
  }

  let nowRate = (time - lastMarker.time) / (nextMarker.time - lastMarker.time);
  nowRate*100;
} else {
  0;
}
```

## 動画レイヤー系

### 動画をいい感じにループする

動画の、時間制御を有効にして、いい感じにループする。
レイヤーの長さの最初と最後がつながるように、一番速度変化が少なくなるように繰り返す。

``` js:タイムリマップ : 動画をいい感じにループする
let src_d = source.duration;
let layer_d = outPoint - inPoint;
let speed = src_d / (layer_d / Math.max(1, Math.round(layer_d/src_d)));
(time * speed) % src_d
```

## おまけ

### テキストエディタでキーフレームを作って貼付けする

キーフレームをコピーしてメモ帳にペーストすると以下が取得できる。
※タブ区切りのテーブル形式データなので、スペースに置換されないように注意！
```
Adobe After Effects 8.0 Keyframe Data

	Units Per Second	30
	Source Width	1082
	Source Height	1594
	Source Pixel Aspect Ratio	1
	Comp Pixel Aspect Ratio	1

ADBE Layer Overrides	Pseudo/@@OugYOmhGQIOl48G2UifXZA-0001 #2
	Frame		
	0	1	
	352	7	
	602	9	


End of Keyframe Data
```
つまり、テキストエディタで一斉置換したり、はたまた別のプログラムから生成することができるのだ。

ちなみに、`Units Per Second ...`から、`...Comp Pixel Aspect Ratio 1`までは無くても貼り付けできるが、想定フレームレートが変わって、微妙なフレームにキーが生成されてずれていく可能性も。
（30fpsのコンポジションに29.97fps計算で配置されるなど）

### SVGで作ったネームタグに大量の名前を複製する

```js:SVGで作ったネームタグに大量の名前を複製する
anchorElem = document.getElementsByTagName('g')[0];
offsetY = 50;

boothList = [
    {index:"1" ,name:"XXXXXXXX"},
    {index:"2" ,name:"XXXXXXXX"},
    {index:"3" ,name:"XXXXXXXX"},
    // ......
];

boothList.forEach((v,i)=>{
    let elem = document.createElementNS('http://www.w3.org/2000/svg','g');
    elem.innerHTML = anchorElem.innerHTML;
    [...elem.children].forEach(vv=>{
        if (vv.hasAttribute('y')) vv.setAttributeNS(null, 'y', vv.getAttribute('y')-0 + offsetY*(i+1));
        else if (vv.hasAttribute('transform')) {
            let y = vv.getAttribute('transform').match(/[\d\.]+/g)[1];
            vv.setAttributeNS(null, 'transform', vv.getAttribute('transform').replace(/\s[\d\.]+\)/, ` ${y-0 + offsetY*(i+1)})`))
        }
    });
    [...elem.getElementsByTagName('tspan')].forEach((vv,ii)=>{
        if (ii==0) {
            vv.innerHTML = (v.name.trim().replace(/&/g, '&amp;'));
        }
        if (ii==1) {
            vv.innerHTML = (v.index.trim());
        }
    });
    document.getElementsByTagName('svg')[0].appendChild(elem);
})
```

グループ化したネームデザインを１つ用意し、そのSVGをブラウザで開いた状態でこのスクリプトを動かす。
目録とか作るのに便利。
僕はこれで150項目くらいのタグを生成しました。