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


エクスプレッションのみで解決!

アプリLINEの動きを再現しようと思ったら結構大変でした。
内容はそうでもないのですが、どうやったらスマートなのか考えてしまいました。

AE画面はこのようになってます。
メッセージ分けしたコンポジションが並べてあるだけです。

完成はこの様な動き

エクスプレッション説明

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

まずは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を超えたら
基点のレイヤーが表示されて超えたレイヤー分のポジションを上にあげています。

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

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;
}

ちょっくら訂正版


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;
}