追記:せっかくなのでテキストやシェイプにも対応させました。
シェイプは線有りには対応しておりません。詳しくは後述の解説へ。
コラップスをかけたリニアワイプは%の基準がコンポ全体になってしまうので、半端な%で調整するしかありません。
なかなか面倒なのでエクスプレッションを組んでみました。
*角度については、厳密にコラップス前の状態にはなりません。詳しくは後述の解説へ。
やり方
リニアワイプを適用したレイヤーにスライダー制御と角度制御を追加します。
”変換終了”と”ワイプ角度”それぞれに以下のエクスプレッションを適用します。
■変換終了
var mSld = effect("スライダー制御")(1);
var mRot = effect("リニアワイプ")(2);
function mGetRotPt(aStdPt, aTgtPt, aStdRot ) {
var mTgtPtZr = aTgtPt - aStdPt;
var mRotRd = aStdRot * (Math.PI / 180);
var mRstX = mTgtPtZr[0] * Math.cos(mRotRd) - mTgtPtZr[1] * Math.sin(mRotRd);
var mRstY = mTgtPtZr[0] * Math.sin(mRotRd) + mTgtPtZr[1] * Math.cos(mRotRd);
return [mRstX,mRstY]+aStdPt;
}
mRot = mRot * -1;
var mCmpW = thisComp.width;
var mCmpH = thisComp.height;
var mCmpUL = [0,0];
var mCmpUR = [mCmpW,0];
var mCmpDL = [0,mCmpH];
var mCmpDR = [mCmpW,mCmpH];
var mRect = thisLayer.sourceRectAtTime(time,false);
var mLyrL = mRect.left;
var mLyrT = mRect.top;
var mLyrR= mLyrL + mRect.width;
var mLyrB= mLyrT + mRect.height;
var mLyrUL = toComp([mLyrL,mLyrT]);
var mLyrUR = toComp([mLyrR,mLyrT]);
var mLyrDL = toComp([mLyrL,mLyrB]);
var mLyrDR = toComp([mLyrR,mLyrB]);
mCmpUL = mGetRotPt( [0,0] , mCmpUL , mRot );
mCmpUR = mGetRotPt( [0,0] , mCmpUR , mRot );
mCmpDL = mGetRotPt( [0,0] , mCmpDL , mRot );
mCmpDR = mGetRotPt( [0,0] , mCmpDR , mRot );
var mCmpSqrAry = [mCmpUL,mCmpUR,mCmpDL,mCmpDR];
mLyrUL = mGetRotPt( [0,0] , mLyrUL , mRot );
mLyrUR = mGetRotPt( [0,0] , mLyrUR , mRot );
mLyrDL = mGetRotPt( [0,0] , mLyrDL , mRot );
mLyrDR = mGetRotPt( [0,0] , mLyrDR , mRot );
var mLyrSqrAry = [mLyrUL,mLyrUR,mLyrDL,mLyrDR];
mCmpSqrAry.sort( function( a , b ){ return a[1] - b[1]; } );
mLyrSqrAry.sort( function( a , b ){ return a[1] - b[1]; } );
var mCmpYMin = mCmpSqrAry[0][1];
var mCmpYMax = mCmpSqrAry[mCmpSqrAry.length-1][1];
var mLyrYMin = mLyrSqrAry[0][1];
var mLyrYMax = mLyrSqrAry[mLyrSqrAry.length-1][1];
var mCmpLgt = mCmpYMax - mCmpYMin;
var mSttPtY = mCmpYMax - mLyrYMax;
var mEndPtY = mCmpYMax - mLyrYMin;
var mSttPct = mSttPtY / mCmpLgt * 100;
var mEndPct = mEndPtY / mCmpLgt * 100;
linear(mSld,0,100,mSttPct,mEndPct);
■ワイプ角度
var mRotCtl = effect("角度制御")(1);
var mRots = [thisLayer.rotation];
var mPrt = thisLayer;
for(var i = 0;i<100;i++){
if( !(mPrt.hasParent) ){
break;
}else{
mPrt = mPrt.parent;
mRots.push(mPrt.rotation);
}
}
var mRstRot = 0;
for(var i = 0;i< mRots.length;i++){
mRstRot = mRstRot + mRots[i];
}
mRstRot + mRotCtl;
スライダー制御の0~100%で、ちょうどレイヤーが現れるようになります!
そして、角度がレイヤーの回転に応じたものになります!
使いどころ
リニアワイプを使いたいが、解像度を保ちたいのでコラップスせざるを得ない…みたいなときに役立ちます。
「写真を仮でコンポに入れといて、本番用に差し替えた。しかしコンポを小さめに作ってしまってコラップスせざるを得ない…」みたいなときですね。
同方向にインアウトさせたい場合、2つのリニアワイプを使う手法があります。
しかしこのエフェクトセットをコピーすると、いちいちエクスプレッション制御の参照エフェクトを書き換えなければなりません。なのでコピーはせず、インアウトそれぞれのアニメーション始まり部分に角度キーを打ち(アウトはインを180度回転させた値)、そして角度キー2つに『停止したキーフレームの置き換え』をするほうがよいやもです。
*元々、レイヤー内の外側部分にアルファがある場合、0~100%ちょっきりにならない場合があります。ただ、これはコラップスしていなくても同様です。
解説
解説用動画を作ってみました。
コラップスすると、0~100%がコンポの端から端になります(どの端から端かはワイプ角度による)。なので、求めたいのはその中でレイヤーの端から端が何%~何%なのか?です。
三角関数やらを使うことも考えたのですが、「全体をガバッとワイプ角度の逆回転させれば、斜めの計算じゃなく単純なY軸計算でよいな」と思いつきました。そしてコンポの四隅Y値、レイヤーの四隅Y値それぞれの最大最小値を出せば、コンポの始点終点、レイヤーの始点終点がわかり、その距離でそれぞれ割合計算すればよい、ということです。
*角度について
親子になっていても角度参照できるように、親子全ての角度を足しています。
しかしコラップス前と比べて、90度や180度などちょっきりした角度ならば同形状になりますが、半端な角度だとちょっと違った形状になってしまいます。
原因はおそらく、コラップス前は角度の中心がレイヤーの中心である(つまり移動できる)のに対し、コラップス後はコンポの中心(常に定位置)であるのでズレるから、
そしてもう一つ、レイヤーの縦横比とコンポの縦横比も関連しているのでは?と考えています。
それらを計算して解消するのはちょっと複雑すぎるので、とりあえず『厳密な再現』には非対応です。
角度にエクスプレッションを付けなくても”変換終了”のエクスプレッションは効きます。
%操作だけでもなかなか役立つので、ぜひともお試しください!
追記:テキストやシェイプに対応させるため、thisLayer.width&heightの代わりにsourceRectAtTimeを使いました。通常のレイヤーであれば、sourceRectAtTimeの結果はthisLayer.width&heightと全く変わらないので、どの種類のレイヤーにも対応できた、ということです。
ただし、sourceRectAtTimeの説明にはたいがい、「sourceRectAtTime(t = time, includeExtents = false)のincludeExtentsをtrueにすれば、線を含めたバウンディングボックスが得られる」的なことが書いてあるんですが、実際は「少なくとも図形を囲ってはいる余裕を持った四角」が得られるだけのようです。
これでは実質0~100%出しをちょっきり計算ができないので、falseにして非対応としてあります。
まあ~線の太さ込みの四隅計算は難しくてリアルタイムで出すのは難しいんだろうなあ…
参照サイト:Adobe Support Community “sourceRectAtTime options confusion”