Hの形の定規が欲しいこと、ままありますよね。そしてラベルも追従してくれると嬉しいですよね。
H型定規シェイプ(.ffx配布あり)「Shape-RulerH」の機能をブラッシュアップしスクリプト化。実質バージョン2的な扱いです。
[概要]
H型の定規シェイプと追従するラベルを作成するスクリプト。
[使い方]
- スクリプトを実行
- シェイプのエフェクトにあるポイントのAとBを定規の両端にセット
- ラベルのソーステキストを打ち替える
- テキストレイヤーの1つ下がシェイプレイヤーという並びだけ崩さず使う
- ラベルのスケールは触らない
[オプション]
- [離す距離]でポイントを移動せずに上下にスライド可能
- [タテ線の長さ]一括変更可能
- [ヨコ線-Y%]で横棒をタテ線の範囲で上下可能
- [線の太さ]、[線の色]、[境界線の太さ]、[境界線の色]は一括変更可能
[解説]
//////////////////////////////////////////////////
// H型の定規シェイプとテキストを生成するスクリプト
//////////////////////////////////////////////////
var actCmp=app.project.activeItem;
function f_Shape_RulerH(){
var shapeLyr = actCmp.layers.addShape();// 空のシェイプレイヤーが作られる
shapeLyr.name="Shape-RulerH";
shapeLyr.label=2;
// セットするエフェクト準備
var efAry=["ポイントA","ポイントB","離す距離","タテ線の長さ","ヨコ線-Y%","線の太さ","線の色","境界線の太さ","境界線の色"];
var efAry2=["ADBE Point Control","ADBE Point Control","ADBE Slider Control","ADBE Slider Control","ADBE Slider Control","ADBE Slider Control","ADBE Color Control","ADBE Slider Control","ADBE Color Control"];
var addAry=[];
//エフェクトを次々適用
for(i=0;i<efAry.length;i++){
addAry[i]=shapeLyr.property("ADBE Effect Parade").addProperty(efAry2[i]);
addAry[i].enabled=false;
addAry[i].name=efAry[i];
}//for
//エフェクトに初期値セット
var pointA=shapeLyr.property("ADBE Effect Parade")(efAry[0])(1);
pointA.setValue(pointA.value-[100,0]);
var pointB=shapeLyr.property("ADBE Effect Parade")(efAry[1])(1);
pointB.setValue(pointB.value+[100,0]);
shapeLyr.property("ADBE Effect Parade")(efAry[2])(1).setValue(50);
shapeLyr.property("ADBE Effect Parade")(efAry[3])(1).setValue(100);
shapeLyr.property("ADBE Effect Parade")(efAry[4])(1).expression=
'if(value<-100){\r'+
' -100;\r'+
'}else if(value>100){\r'+
' 100;\r'+
'}else{\r'+
' value;\r'+
'}';
shapeLyr.property("ADBE Effect Parade")(efAry[5])(1).setValue(2);
shapeLyr.property("ADBE Effect Parade")(efAry[6])(1).setValue([255,0,0,255]/255);//赤
shapeLyr.property("ADBE Effect Parade")(efAry[8])(1).setValue([255,255,255,255]/255);//白
var shapeProperty = shapeLyr.property("ADBE Root Vectors Group"); // これにシェイプを追加していく
var shapeGroup1 = shapeProperty.addProperty("ADBE Vector Group");
shapeGroup1.name="ヨコ線";
/* 長方形パスを3つ準備+エクスプレッションもセットしていく */
var shapePath1 = shapeGroup1.addProperty("ADBE Vectors Group").addProperty("ADBE Vector Shape - Rect");
//サイズ
shapePath1(2).expression=
'var p1=effect("ポイントA")("ポイント");\r'+
'var p2=effect("ポイントB")("ポイント");\r'+
'\r'+
'[length(p1,p2),effect("線の太さ")(1)];'
//位置
shapePath1(3).expression=
'var a=effect("タテ線の長さ")(1)/200;\r'+
'\r'+
'[0,effect("線の太さ")(1)%2/2+(effect("ヨコ線-Y%")(1)*a)-effect("離す距離")(1)];';
shapeGroup1.property("ADBE Vector Transform Group").property("ADBE Vector Position").expression=
'var anchor=[thisComp.width/2,thisComp.height/2];\r'+
'var p1=effect("ポイントA")(1)-anchor;\r'+
'var p2=effect("ポイントB")(1)-anchor;\r'+
'\r'+
'[(p1[0]+p2[0])/2,(p1[1]+p2[1])/2];';
shapeGroup1.property("ADBE Vector Transform Group").property("ADBE Vector Rotation").expression=
'var anchor=[thisComp.width/2,thisComp.height/2];\r'+
'var p1=effect("ポイントA")("ポイント")-anchor;\r'+
'var p2=effect("ポイントB")("ポイント")-anchor;\r'+
'var a=(p2-p1);\r'+
'var angle=Math.atan2(a[1],a[0]);\r'+
'\r'+
'radiansToDegrees(angle)';
var shapeGroup2 = shapeProperty.addProperty("ADBE Vector Group");
shapeGroup2.name="タテ線A";
var shapePath2 = shapeGroup2.addProperty("ADBE Vectors Group").addProperty("ADBE Vector Shape - Rect");
//サイズ
shapePath2(2).expression=
'[effect("線の太さ")(1),effect("タテ線の長さ")(1)];'
//位置
shapePath2(3).expression=
'[0,-effect("離す距離")(1)];';
shapeGroup2.property("ADBE Vector Transform Group").property("ADBE Vector Position").expression=
'var anchor=[thisComp.width/2,thisComp.height/2];\r'+
'\r'+
'effect("ポイントA")(1)-anchor;';
shapeGroup2.property("ADBE Vector Transform Group").property("ADBE Vector Rotation").expression=
'var anchor=[thisComp.width/2,thisComp.height/2];\r'+
'var p1=effect("ポイントA")("ポイント")-anchor;\r'+
'var p2=effect("ポイントB")("ポイント")-anchor;\r'+
'var a=(p2-p1);\r'+
'var angle=Math.atan2(a[1],a[0]);\r'+
'\r'+
'radiansToDegrees(angle)';
var shapeGroup3 = shapeProperty.addProperty("ADBE Vector Group");
shapeGroup3.name="タテ線B";
var shapePath3 = shapeGroup3.addProperty("ADBE Vectors Group").addProperty("ADBE Vector Shape - Rect");
//サイズ
shapePath3(2).expression=
'[effect("線の太さ")(1),effect("タテ線の長さ")(1)];'
//位置
shapePath3(3).expression=
'[0,-effect("離す距離")(1)];';
shapeGroup3.property("ADBE Vector Transform Group").property("ADBE Vector Position").expression=
'var anchor=[thisComp.width/2,thisComp.height/2];\r'+
'\r'+
'effect("ポイントB")(1)-anchor;';
shapeGroup3.property("ADBE Vector Transform Group").property("ADBE Vector Rotation").expression=
'var anchor=[thisComp.width/2,thisComp.height/2];\r'+
'var p1=effect("ポイントA")("ポイント")-anchor;\r'+
'var p2=effect("ポイントB")("ポイント")-anchor;\r'+
'var a=(p2-p1);\r'+
'var angle=Math.atan2(a[1],a[0]);\r'+
'\r'+
'radiansToDegrees(angle)';
shapeProperty.addProperty("ADBE Vector Filter - Merge");// パスを結合
// 塗り
shapeProperty.addProperty("ADBE Vector Graphic - Fill").property("ADBE Vector Fill Color").expression=
'effect("'+efAry[6]+'")(1);';
var stroke=shapeProperty.addProperty("ADBE Vector Graphic - Stroke");
stroke.property("ADBE Vector Stroke Width").expression=
'effect("'+efAry[7]+'")(1);';
stroke.property("ADBE Vector Stroke Color").expression=
'effect("'+efAry[8]+'")(1);';
/* 定規に追従するテキストレイヤーを作成 */
var textLyr=actCmp.layers.addText("100");
// 中央揃えにしておく
var txPrp=textLyr.property("Source Text");
var txSTS=txPrp.value;
txSTS.justification=ParagraphJustification.CENTER_JUSTIFY;
txPrp.setValue(txSTS);
// エクスプレッションも適用していく
textLyr.property("ADBE Transform Group").property("ADBE Anchor Point").expression=
'var ruler=thisComp.layer(index+1);\r'+
'var a=ruler.effect("'+efAry[3]+'")(1)/200;\r'+
'\r'+
'[0,(-ruler.effect("'+efAry[4]+'")(1)*a)+ruler.effect("'+efAry[2]+'")(1)]+value;';
// アンカーポイントのvalueは少し上に
textLyr.property("ADBE Transform Group").property("ADBE Anchor Point").setValue([0,20]);
textLyr.property("ADBE Transform Group").property("ADBE Position").expression=
'var ruler=thisComp.layer(index+1);\r'+
'var p1=ruler.effect("ポイントA")(1);\r'+
'var p2=ruler.effect("ポイントB")(1);\r'+
'\r'+
'[(p1[0]+p2[0])/2,(p1[1]+p2[1])/2]+value;';
// 位置のvalueは0に
textLyr.property("ADBE Transform Group").property("ADBE Position").setValue([0,0]);
textLyr.property("ADBE Transform Group").property("ADBE Rotate Z").expression=
'thisComp.layer(index+1).content("ヨコ線").transform.rotation';
// スケールは100%固定に
textLyr.property("ADBE Transform Group").property("ADBE Scale").expression=
'[100,100]';
textLyr.selected=false;
shapeLyr.selected=true;// シェイプレイヤーを選択状態にして締め
}
app.beginUndoGroup("Shape-RulerH");
f_Shape_RulerH();
app.endUndoGroup();
まずはシェイプレイヤーを準備します。スクリプトでシェイプを作ると記述が面倒ですが、仕方ありません。
まずは8行目、addShape()します。ただの空のシェイプレイヤーを準備し、パスや塗りなどプロパティはいちいち指定してぶち込んでいきます。一応、リネームとラベルを黄色にしました。
13行目からはエクスプレッション制御エフェクトをそこそこ追加するので、処理をまとめてあります。任意のエフェクト名と、対応する型のエクスプレッション制御をマッチネームで配列に入れます。
18行目からこれらをfor文で回しながら連続で追加→リネームさせます。また、メモリ?キャッシュ?を汚さない?というおまじないのfxオフ化しておきます。エクスプレッション制御はvalueをエクスプレッションで持ち出して使うので、エフェクト自体はオフ状態で構いません。
25行目から、追加したエフェクトの初期値と、必要ならエクスプレッションをセットしていきます。
43行目でシェイプレイヤー内のグループを取得しておいて、変数で使い回せるようにします。
44行目はこれも空のグループを作ります。この辺の構造がややこしいです。普段、シェイプツールで作られるシェイプレイヤーには、グループやトランスフォームが自動で追加されますが、スクリプトからは明示的に追加してやらなくてはなりません。シェイプはヨコ線が1つ、両端用のタテ線が2つと長方形シェイプを3つ作るため、識別しやすいように一応リネームしておきます。処理上は使いません。整理のためだけですので、45行目と、その後の同じ処理の76行目、98行目はなくてもOKです。
48行目が長方形パスを追加する部分です。サイズはエクスプレッションでエフェクトのポイントABの長さに連動するようにします。ヨコ線>長方形パス 1>サイズにエクスプレッションを追加です。
var p1=effect("ポイントA")("ポイント");
var p2=effect("ポイントB")("ポイント");
[length(p1,p2),effect("線の太さ")(1)];
ちょうどエクスプレッションに2点間の長さを取得するlength([x1,y1],[x2,y2])があるので、使います。
56行目、ヨコ線>長方形パス 1>位置にエクスプレッションを追加。
var a=effect("タテ線の長さ")(1)/200;
[0,effect("線の太さ")(1)%2/2+(effect("ヨコ線-Y%")(1)*a)-effect("離す距離")(1)];
effect(“線の太さ”)が奇数の場合、0.5pxズラさないとピクセルを跨ぐことで線が滲むため%2/2してやります。偶数で0、奇数で0.5足されます。その後、effect(“ヨコ線-Y%”)の数値だけ上下させる分と、effect(“離す距離”)でスライドする分を組み込んで完了です。
60行目はヨコ線>トランスフォーム:位置用のエクスプレッションをセットします。ヨコ線>長方形パス 1>位置ではなく、長方形パス 1の下のトランスフォームの位置です。これで、ポイントABの中間地点に長方形のセンターが来るように調整します。
var anchor=[thisComp.width/2,thisComp.height/2];
var p1=effect("ポイントA")(1)-anchor;
var p2=effect("ポイントB")(1)-anchor;
[(p1[0]+p2[0])/2,(p1[1]+p2[1])/2];
シェイプレイヤーはコンポジション中央が[0,0]です。なんでや。なのでコンポジションの座標とシェイプの座標を噛み合わせるための処理です。[0,0]がど真ん中ということは、コンポジションの幅と高さの半分をマイナスしてやれば合います。ここから、2点間の中央を計算する、[x1+x2/2,y1+y2/2]の公式に当てはめて完了です。
66行目、ヨコ線>トランスフォーム:回転用のエクスプレッションをセットします。座標は今やったあれこれをコピペして使い、
var anchor=[thisComp.width/2,thisComp.height/2];
var p1=effect("ポイントA")("ポイント")-anchor;
var p2=effect("ポイントB")("ポイント")-anchor;
var a=(p2-p1);
var angle=Math.atan2(a[1],a[0]);
radiansToDegrees(angle)
アークタンジェントでラジアンを導いて、角度に変換します。
75行目から2つめのシェイプ、タテ線の1個目です。大体ヨコ線の応用でいけます。
79行目でタテ線A>長方形パス 1>サイズにエクスプレッション。ヨコ線と同じくeffect(“離す距離”)分スライドさせます。
[0,-effect("離す距離")(1)];
84行目、タテ線A>トランスフォーム:位置にエクスプレッション。ヨコ線と同じくタテ線A>長方形パス 1>トランスフォームでないことに注意。
var anchor=[thisComp.width/2,thisComp.height/2];
effect("ポイントA")(1)-anchor;
これでポイントAの位置に持ってきます。ちょうどヨコ線の端になります。
88行目でタテ線A>トランスフォーム:回転にエクスプレッション。ヨコ線の傾きと一緒でいいのでコピペです。
var anchor=[thisComp.width/2,thisComp.height/2];
var p1=effect("ポイントA")("ポイント")-anchor;
var p2=effect("ポイントB")("ポイント")-anchor;
var a=(p2-p1);
var angle=Math.atan2(a[1],a[0]);
radiansToDegrees(angle)
97行目からタテ線のBです。違うところはポイントのBに追従する部分だけ。あとはタテ線Aと一緒なのでここだけ解説です。
106行目、タテ線B>トランスフォーム:位置にエクスプレッション。
var anchor=[thisComp.width/2,thisComp.height/2];
effect("ポイントB")(1)-anchor;
これでポイントBの位置に持ってこれます。あとのタテ線Bの説明は飛ばします。
119行目で[パスを結合]を追加。境界線も組み込んだので、結合しないと3つの長方形それぞれで境界線が重なって表示されてしまいます。3つの長方形の後ろに境界線ができて欲しいので結合です。
121行目で結合したパス用の塗りを追加し、エクスプレッションでeffect(“線の色”)を引っ張ります。
123行目で線を追加すると、線幅とカラーも自動で追加されるため、124行目でeffect(“境界線の色”)、126行目でeffect(“境界線の太さ”)をエクスプレッションで引っ張ります。
シェイプレイヤーはこれで終わりです。130行目で定規のラベルとして使うテキストレイヤーを作り、定規に追従する仕掛けをしていきます。デフォルトのソーステキストに適当な”100″を入れておきます。
132行目からテキストは中央揃えが使いやすいので、段落を中央に設定します。これも面倒な仕様で簡単にセットできず、ソーステキストのvalueという親扱いのプロパティに段落の中央揃えを入れた箱をsetValueする必要があります。おそらく誰しもひっかかります。
138行目からトランスフォームにエクスプレッションを仕込んでいきます。もう一息です。
アンカーポイントに
var ruler=thisComp.layer(index+1);
var a=ruler.effect("タテ線の長さ")(1)/200;
[0,(-ruler.effect("ヨコ線-Y%")(1)*a)+ruler.effect("離す距離")(1)]+value;
とし、シェイプレイヤーのエフェクトにアクセスします。タイムライン上で1つ下のレイヤーがシェイプレイヤーと仮定し、index+1にしているので、必ずテキストレイヤーの直下に定規のシェイプのレイヤーがある状態を保ってください。レイヤー順を変更したい場合は、2つのレイヤーをまとめて移動してください。effect(“タテ線の長さ”)を200等分し、-100~+100で位置決めします。effect(“離す距離”)も追従したいので組み込みます。場合によってテキストだけ位置を微調整したいこともあるので、valueを残しておきます。
144行目はヨコ線のちょっと上にラベルが欲しいので、角度が変わってもいい感じにヨコ線の12時方向に移動したいので、アンカーポイントのvalue自体を[0,20]しておきます。
145行目がラベルをヨコ線と同じくポイントABの中間に持ってくるエクスプレッションです。テキストレイヤー>位置に
var ruler=thisComp.layer(index+1);
var a=ruler.effect("タテ線の長さ")(1)/200;
[0,(-ruler.effect("ヨコ線-Y%")(1)*a)+ruler.effect("離す距離")(1)]+value;
これを仕込みます。
テキストレイヤーはコンポジションの左上が[0,0]なのでこの処理でズレますので、152行目でテキストのvalueは[0,0]にして位置を合わせます。
153行目、ヨコ線と同じ傾きに調整するエクスプレッションを仕込みます。
thisComp.layer(index+1).content("ヨコ線").transform.rotation
回転の指定だけ、property(“ADBE Rotation”)は存在せずエラー、property(“ADBE Rotate Z”)を指定するのだけ注意です。2Dレイヤーでも内部的には3DレイヤーのZ回転と同じものです。2Dレイヤー状態ではX回転、Y回転が非表示になり、Z回転が回転に表記だけ変わっています。
156行目ではテキストのスケールが変更できないよう固定します。アンカーポイントを位置調整に使用したため、スケールを変えるとズレます。仕様です。
最後に、スクリプト実行後にはすぐにエフェクトのポイントA、ポイントBを触れるように、159行目から最後の処理をしているテキストレイヤーの選択を解除し、シェイプレイヤーを選択状態にしてQ.E.D.!
この記事へのコメントはありません。