AE　エクスプレッションのみでLINEメッセージ画面をアニメート

#エクスプレッションのみで解決！
アプリLINEの動きを再現しようと思ったら結構大変でした。
内容はそうでもないのですが、どうやったらスマートなのか考えてしまいました。

AE画面はこのようになってます。
メッセージ分けしたコンポジションが並べてあるだけです。
![bandicam 2018-08-20 14-35-28-478.jpg](https://qiita-image-store.s3.amazonaws.com/0/178061/f0575585-a6e7-6fc2-2217-dbc0a853afe5.jpeg)


完成はこの様な動き

![640.gif](https://qiita-image-store.s3.amazonaws.com/0/178061/cd7d26ee-11a9-b81f-5563-519dbfe0cc76.gif)


#エクスプレッション説明
基本的に最初のメッセージの位置を変えていく形にしました。
基点となるレイヤーは最初のメッセージレイヤーだけです。
他のレイヤーはそれについていく形です。
実際には下のレイヤーのポジションについていきます。

まずはtry{}cathe{}
でこのレイヤーが基点かどうかを定義しています。
このレイヤーが基点でなければ

var check = layerRefer.name.split(/\s+/)[0];
これはレイヤーの名前を/で分けてます。
実際のcheckにはgrpというstringが格納されています。

if ( check == 'msg' && layerRefer.active)
こちらはレイヤー名に"msg"が含まれていてレイヤーがアクティブの場合

var temp = layerRefer.height/2;
var x = thisLayer.width/2;
var  y =  temp+layerRefer.position[1]+thisLayer.height/2+pad ;
[x,y]；
これで下のレイヤーのポジションの下にthislayerのレイヤーが来るように設定しています。

最初のtryで基点となるレイヤーの場合これはいわゆるthislayerのインデックスより上の数字でmsgのレイヤーがなければという事になります。
これで基点か判断して基点であれば
    if (xxx() > bottomPosition ){
        [thisLayer.width/2,260+bottomPosition -xxx()]
    }
    else{
        [thisLayer.width/2,260+thisLayer.height/2]
    }
を適応します。

これは最初に決めた1550px;　//折り返すポジションを
超えた場合と超えない場合の処理です。
これにより1550pxを超えたら
基点のレイヤーが表示されて超えたレイヤー分のポジションを上にあげています。

説明が本当に下手ですみません。



```jsx
var CinLNum = thisComp.numLayers; //レイヤー総数
var myIndexNum = thisLayer.index;//レイヤーインデックス
var bottomPosition = 1550;　//折り返すポジション
var pad = 50;　//コンポジション間のパディング

for ( var i = myIndexNum ; i <= CinLNum ; i++){
    try{
        var layerRefer = thisComp.layer(i+1);
        var check = layerRefer.name.split(/\s+/)[0];
        if ( check == 'msg' && layerRefer.active){
            var temp = layerRefer.height/2;
            var x = thisLayer.width/2;
            var  y =  temp+layerRefer.position[1]+thisLayer.height/2+pad ;
            [x,y]
        break;
        }
    }
    catch (e){
        e  
    }
    if (xxx() > bottomPosition ){
        [thisLayer.width/2,260+bottomPosition -xxx()]
    }
    else{
        [thisLayer.width/2,260+thisLayer.height/2]
    }
}

function xxx(){
    var temp = 0;
    for ( var i = myIndexNum ; i >= 1 ; i--){
    var layerRefer = thisComp.layer(i);
    var check = layerRefer.name.split(/\s+/)[0];
        if ( check == 'msg' && layerRefer.active){
            temp = temp + layerRefer.height+ pad;
        }
    }
    return temp;
}
```

###ちょっくら訂正版

```jsx

var CinLNum = thisComp.numLayers;
var myIndexNum = thisLayer.index;
var firstposition = 260;
var bottomPosition = 1800;
var pad = 50;

for ( var i = myIndexNum ; i <= CinLNum ; i++){
    try{
        var layerRefer = thisComp.layer(i+1);
        var check = layerRefer.name.split(/\s+/)[0];
        if ( check == 'msg' && layerRefer.active){
            var temp = layerRefer.height/2;
            var x = thisLayer.width/2;
            var  y =  temp+layerRefer.position[1]+thisLayer.height/2+pad ;
            [x,y]
        break;
        }
    }
    catch (e){
        e  
    }
    if (xxx() > bottomPosition-pad  ){
        [thisLayer.width/2,firstposition+bottomPosition -xxx()]
    }
    else{
        [thisLayer.width/2,firstposition+thisLayer.height/2]
    }
}
function xxx(){
    var temp = 0;
    for ( var i = myIndexNum ; i >= 1 ; i--){
    var layerRefer = thisComp.layer(i);
    var check = layerRefer.name.split(/\s+/)[0];
        if ( check == 'msg' && layerRefer.active){
            temp = temp + layerRefer.height+ pad;
        }
    }
    return temp+firstposition/2+pad*2;
}
```