【エクスプレッション】線付きリニアワイプ

エフェクト欄だけで完結する線ワイプのエクスプレッションです。

STEP
まずは画像にエフェクトを適用する。

エクスプレッション制御/スライダー制御

  • 30%(線の太さ用。掛かってるか確認のため、ちょっとだけ数値を上げておく)

トランジション/リニアワイプ

  • 変換終了:50%(掛かってるかの確認用)

描画/レーザー

  • 長さ:100
  • 柔らかさ:0
  • 内側のカラー:白
  • 外側のカラー:白
  • 3D遠近法:チェックなし
  • 元を合成:チェックあり
STEP
レーザー『開始点』『終了点』に以下のエクスプレッションをコピペ。

開始点

//基準点と目標点と角度から、回転した目標点の位置を出す関数。
function mGetRotatedPt( aStdPt , aTgtPt , aRtn ){
	var mLgtRX = aTgtPt[0] - aStdPt[0];
	var mLgtRY = aTgtPt[1] - aStdPt[1];
	var mLgtR = Math.sqrt( Math.pow( mLgtRX , 2 ) +Math.pow( mLgtRY , 2 ) );
				
	var mROgl =  Math.atan2 ( ( mLgtRY ) , ( mLgtRX ) );
	var mRd =  aRtn * ( Math.PI / 180 ) ;
	var mPtR =  [ Math.cos( mROgl + mRd ) * mLgtR , Math.sin( mROgl + mRd ) * mLgtR ];

	return mPtR + aStdPt;
}

//点は4つ必要なので処理をまとめた関数。
function mMakeRotPt( aRtn ){
	var mRtn = aRtn;
	//0~360未満までを繰り返す回転。
	var mRtnRoop = mRtn % 360;
	//マイナス対策をする。
	if( mRtnRoop < 0 ){ mRtnRoop = 360 + mRtnRoop; };
	//90度ごとに増えるカウンター。
	var mCnt = Math.floor( mRtnRoop / 90 );

	//下記回転位置はそれぞれ180度区切りで2つに分かれるものが2つある状態で、
	//カウンターを使って90度ごとに横軸上円(0~180)、縦軸右円(0~180)、
	//横軸下円(180~360)、縦軸左円(180~360)用へと移り変わる角度を作る。
	if( mCnt === 0 ){
	var mNewRtn = linear(mRtnRoop , 0 , 90 ,  0 , 180 );
	}else if( mCnt === 2 ){
	var mNewRtn = linear(mRtnRoop , 180 , 270 ,  180 , 360 );
	}else if( mCnt === 1 ){
	var mNewRtn = linear(mRtnRoop , 90 , 180 ,  0 , 180 );
	}else if( mCnt === 3 ){
	var mNewRtn = linear(mRtnRoop , 270 , 360 ,  180 , 360 );
	}

	//カウンターを使って、角度が0~90と180~270の場合は横軸上円&下円の値を使い、
	//90~180と270~360の場合は縦軸右円&左円を使うようにする。
	if( mCnt === 0 || mCnt === 2 ){
		var mStdPt = [thisLayer.width / 2 ,0 ];
		var mTgtPt = [0 , 0];
		var mRttPt = mGetRotatedPt( mStdPt , mTgtPt , mNewRtn );
		//ターゲットが原点の横軸円を、180度区切りで下に移行するよう分ける。
		if( mNewRtn >= 180 ){
			mRttPt = mRttPt+[0,thisLayer.height];
		}
	}else{
		var mStdPt = [0 , thisLayer.height / 2];
		var mTgtPt = [0 , 0];
		var mRttPt = mGetRotatedPt( mStdPt , mTgtPt , mNewRtn );
		//ターゲットが原点の縦軸円を、180度までは右円になるよう分ける。
		if( mNewRtn < 180 ){
			mRttPt = mRttPt + [thisLayer.width,0];
		}
	}
	return mRttPt;
}

var mRtn = effect("リニアワイプ")("ワイプ角度");
var mRotPt1 = mMakeRotPt( mRtn );
var mRotPt2 = mMakeRotPt( mRtn +90 );
var mRotPt3 = mMakeRotPt( mRtn +180 );
var mRotPt4 = mMakeRotPt( mRtn +270 );

var mPct = effect("リニアワイプ")("変換終了");
linear( mPct , 0 , 100 , mRotPt4 , mRotPt1 );

終了点

//基準点と目標点と角度から、回転した目標点の位置を出す関数。
function mGetRotatedPt( aStdPt , aTgtPt , aRtn ){
	var mLgtRX = aTgtPt[0] - aStdPt[0];
	var mLgtRY = aTgtPt[1] - aStdPt[1];
	var mLgtR = Math.sqrt( Math.pow( mLgtRX , 2 ) +Math.pow( mLgtRY , 2 ) );
				
	var mROgl =  Math.atan2 ( ( mLgtRY ) , ( mLgtRX ) );
	var mRd =  aRtn * ( Math.PI / 180 ) ;
	var mPtR =  [ Math.cos( mROgl + mRd ) * mLgtR , Math.sin( mROgl + mRd ) * mLgtR ];

	return mPtR + aStdPt;
}

//点は4つ必要なので処理をまとめた関数。
function mMakeRotPt( aRtn ){
	var mRtn = aRtn;
	//0~360未満までを繰り返す回転。
	var mRtnRoop = mRtn % 360;
	//マイナス対策をする。
	if( mRtnRoop < 0 ){ mRtnRoop = 360 + mRtnRoop; };
	//90度ごとに増えるカウンター。
	var mCnt = Math.floor( mRtnRoop / 90 );

	//下記回転位置はそれぞれ180度区切りで2つに分かれるものが2つある状態で、
	//カウンターを使って90度ごとに横軸上円(0~180)、縦軸右円(0~180)、
	//横軸下円(180~360)、縦軸左円(180~360)用へと移り変わる角度を作る。
	if( mCnt === 0 ){
	var mNewRtn = linear(mRtnRoop , 0 , 90 ,  0 , 180 );
	}else if( mCnt === 2 ){
	var mNewRtn = linear(mRtnRoop , 180 , 270 ,  180 , 360 );
	}else if( mCnt === 1 ){
	var mNewRtn = linear(mRtnRoop , 90 , 180 ,  0 , 180 );
	}else if( mCnt === 3 ){
	var mNewRtn = linear(mRtnRoop , 270 , 360 ,  180 , 360 );
	}

	//カウンターを使って、角度が0~90と180~270の場合は横軸上円&下円の値を使い、
	//90~180と270~360の場合は縦軸右円&左円を使うようにする。
	if( mCnt === 0 || mCnt === 2 ){
		var mStdPt = [thisLayer.width / 2 ,0 ];
		var mTgtPt = [0 , 0];
		var mRttPt = mGetRotatedPt( mStdPt , mTgtPt , mNewRtn );
		//ターゲットが原点の横軸円を、180度区切りで下に移行するよう分ける。
		if( mNewRtn >= 180 ){
			mRttPt = mRttPt+[0,thisLayer.height];
		}
	}else{
		var mStdPt = [0 , thisLayer.height / 2];
		var mTgtPt = [0 , 0];
		var mRttPt = mGetRotatedPt( mStdPt , mTgtPt , mNewRtn );
		//ターゲットが原点の縦軸円を、180度までは右円になるよう分ける。
		if( mNewRtn < 180 ){
			mRttPt = mRttPt + [thisLayer.width,0];
		}
	}
	return mRttPt;
}

var mRtn = effect("リニアワイプ")("ワイプ角度");
var mRotPt1 = mMakeRotPt( mRtn );
var mRotPt2 = mMakeRotPt( mRtn +90 );
var mRotPt3 = mMakeRotPt( mRtn +180 );
var mRotPt4 = mMakeRotPt( mRtn +270 );

var mPct = effect("リニアワイプ")("変換終了");
linear( mPct , 0 , 100 , mRotPt3 , mRotPt2 );

*開始点と終了点の違いは最後の行だけです。

STEP
レーザー『開始点の太さ』『終了点の太さ』両方に以下のエクスプレッションをコピペ。

『開始点の太さ』と『終了点の太さ』の両方に適用。

var mStop = effect("リニアワイプ")("変換終了");
if( mStop <= 0 || 100 <= mStop ){
	var mRst = 0;
}else{
	var mRst = effect("スライダー制御")("スライダー");
}
mRst;

以上です!
『スライダー制御』で線の太さが変えられます。調整するには『変換の終了』『ワイプ角度』です。リニアワイプとまったく一緒ですね。

使いどころ

「線付きのワイプで映像がどんどん移り変わる」みたいな映像は、オシャレな映画のOPとかで案外使われています。しかしAEって線付きのワイプが無いですよね?(もしかしてあります…?)作例がなんとも地味なTipとなりますがご参考下さい。エフェクトのみで完結しており、レイヤーが増えないのがいいですね。

解説

以下、かんたんな作成経緯&解説です。

  1. おしゃれ映画(『マイレージマイライフ』だったか…)を見て、作りたいなあと思う。
  2. エフェクトのワイプを観察すると、始点と終点は必ず四隅のどこかに当たっている。
  3. もしかして、画像外で回りつつぴったり貼りつく『逆バウンディングボックス』を作ればよいのでは?
  1. 三角関数で最後まで完成。それを見てあることに気付く。
  1. 『逆バウンディングボックス』の四隅は、幅や高さの半分を中心に半円が回っている。ならば…
  2. 画像の大きさ+角度から位置を割り出す関数+リニア関数』を使って直感的なバージョンができる!

という具合です。

一応、三角関数版も載せておきます。コピペする文が違うだけで、使い方は一緒です。どちらが重いのか…?体感上はそんなに違いが無く、行数もあんまり変わってないです。お好きなほうをお使い下さい。

三角関数版も開始点と終了点の違いは最後だけです。

三角関数版開始点

function mMakeRotPtTri( aRot ){
	//逆バウンディングボックスは四隅が必ず90度のため、
	//回転方向と合わせれば3角度全てが出る、かつ直角三角形、かつ斜辺(画像のWorH)もわかる。
	//なので三角比を使って四隅を出す。
	
	//シータの元となる任意の角度。UIは上方向がゼロで始まる角度であることに注意する。
	var mRot = aRot;
	var mW = thisComp.width;
	var mH = thisComp.height;

	//四隅それぞれの基準原点(シータがある点、扇の持ち手)からの長さ。斜辺(画像WorH)*cosシータ。
	//シータは斜辺(画像のWorH)の向きと任意角度を鑑みて出す。
	var mLgt1 = mW * Math.cos(degreesToRadians( 90 - mRot));
	var mLgt2 = mH * Math.cos(degreesToRadians( 180 - mRot));
	var mLgt3 = mW * Math.cos(degreesToRadians( 270 - mRot));
	var mLgt4 = mH * Math.cos(degreesToRadians( 0 - mRot));

	//aStdPt位置からaLgtの距離の、aRot回転した点を出す関数。 
	//-90して開始角度を上方向にしてある。
	function mGetRotPt( aLgt , aRot , aStdPt ){
		var mRotTmp = aRot - 90;
		var mX = (aLgt * Math.cos(degreesToRadians(mRotTmp ))) + aStdPt[0];
		var mY = (aLgt * Math.sin(degreesToRadians(mRotTmp ))) + aStdPt[1];
		return [mX , mY];
	}

	//0~360未満までを繰り返す回転。
	var mRotRoop = mRot % 360;
	//マイナス対策をする。
	if( mRotRoop < 0 ){ mRotRoop = 360 + mRotRoop; };
	//90度ごとに増えるカウンター。
	var mCnt = Math.floor( mRotRoop / 90 );

	if( mCnt === 0 ){
		var mNewRot = mGetRotPt( mLgt1 , mRot , [0,0] );
	}else if( mCnt === 1 ){
		var mNewRot = mGetRotPt( mLgt2 , mRot , [mW,0] );
	}else if( mCnt === 2 ){
		var mNewRot =  mGetRotPt( mLgt3 , mRot , [mW,mH] );
	}else if( mCnt === 3 ){
		var mNewRot = mGetRotPt( mLgt4 , mRot , [0,mH] );
	}
	return mNewRot;
}

var mRot = effect("リニアワイプ")("ワイプ角度");
var mRotPt1 = mMakeRotPtTri( mRot );
var mRotPt2 = mMakeRotPtTri( mRot +90 );
var mRotPt3 = mMakeRotPtTri( mRot +180 );
var mRotPt4 = mMakeRotPtTri( mRot +270 );

var mPct = effect("リニアワイプ")("変換終了")
linear( mPct , 0 , 100 , mRotPt4 , mRotPt1 );

三角関数版終了点

function mMakeRotPtTri( aRot ){
	//逆バウンディングボックスは四隅が必ず90度のため、
	//回転方向と合わせれば3角度全てが出る、かつ直角三角形、かつ斜辺(画像のWorH)もわかる。
	//なので三角比を使って四隅を出す。
	
	//シータの元となる任意の角度。UIは上方向がゼロで始まる角度であることに注意する。
	var mRot = aRot;
	var mW = thisComp.width;
	var mH = thisComp.height;

	//四隅それぞれの基準原点(シータがある点、扇の持ち手)からの長さ。斜辺(画像WorH)*cosシータ。
	//シータは斜辺(画像のWorH)の向きと任意角度を鑑みて出す。
	var mLgt1 = mW * Math.cos(degreesToRadians( 90 - mRot));
	var mLgt2 = mH * Math.cos(degreesToRadians( 180 - mRot));
	var mLgt3 = mW * Math.cos(degreesToRadians( 270 - mRot));
	var mLgt4 = mH * Math.cos(degreesToRadians( 0 - mRot));

	//aStdPt位置からaLgtの距離の、aRot回転した点を出す関数。 
	//-90して開始角度を上方向にしてある。
	function mGetRotPt( aLgt , aRot , aStdPt ){
		var mRotTmp = aRot - 90;
		var mX = (aLgt * Math.cos(degreesToRadians(mRotTmp ))) + aStdPt[0];
		var mY = (aLgt * Math.sin(degreesToRadians(mRotTmp ))) + aStdPt[1];
		return [mX , mY];
	}

	//0~360未満までを繰り返す回転。
	var mRotRoop = mRot % 360;
	//マイナス対策をする。
	if( mRotRoop < 0 ){ mRotRoop = 360 + mRotRoop; };
	//90度ごとに増えるカウンター。
	var mCnt = Math.floor( mRotRoop / 90 );

	if( mCnt === 0 ){
		var mNewRot = mGetRotPt( mLgt1 , mRot , [0,0] );
	}else if( mCnt === 1 ){
		var mNewRot = mGetRotPt( mLgt2 , mRot , [mW,0] );
	}else if( mCnt === 2 ){
		var mNewRot =  mGetRotPt( mLgt3 , mRot , [mW,mH] );
	}else if( mCnt === 3 ){
		var mNewRot = mGetRotPt( mLgt4 , mRot , [0,mH] );
	}
	return mNewRot;
}

var mRot = effect("リニアワイプ")("ワイプ角度");
var mRotPt1 = mMakeRotPtTri( mRot );
var mRotPt2 = mMakeRotPtTri( mRot +90 );
var mRotPt3 = mMakeRotPtTri( mRot +180 );
var mRotPt4 = mMakeRotPtTri( mRot +270 );

var mPct = effect("リニアワイプ")("変換終了")
linear( mPct , 0 , 100 , mRotPt3 , mRotPt2 );

以上です!
FFXとかプロジェクトを作っておいてご活用ください。

よかったらシェアしてね!
  • URLをコピーしました!