単一行の2Dポイントテキストで揃えと位置を補正する
対象は、親のない2Dポイントテキストを1行で入力した練習レイヤーです。
位置の数値を固定する方法ではなく、揃え変更で動いた文字の矩形を補うように位置を変更します。
別名保存した練習コンポで、クリックして横書きの「AB」を入力し、左揃え・位置300,200・スケール100%・回転0度にします。
レイヤーを選択し、下のコードをalign-text.jsxとしてUTF-8で保存して「ファイル」→「スクリプト」→「スクリプトファイルを実行」から実行します。
初期設定は中央揃えで、変更前後の文字の左上がコンポ内で同じ位置にあるか確認します。
(function () {
var TARGET = ParagraphJustification.CENTER_JUSTIFY;
var comp = app.project && app.project.activeItem;
if (!(comp instanceof CompItem)) { alert("Open a composition."); return; }
var layers = comp.selectedLayers, targets = [], i;
if (!layers.length || layers.length > 20) { alert("Select 1 to 20 practice text layers."); return; }
function staticProp(prop) { return prop && !prop.numKeys && prop.expression === ""; }
for (i = 0; i < layers.length; i++) {
var layer = layers[i];
if (!(layer instanceof TextLayer) || layer.locked || layer.threeDLayer || layer.parent ||
layer.autoOrient !== AutoOrientType.NO_AUTO_ORIENT) {
alert("Use unlocked, unparented 2D text with auto-orient disabled."); return;
}
var text = layer.property("ADBE Text Properties"), source = text.property("ADBE Text Document");
var transform = layer.property("ADBE Transform Group");
var pos = transform.property("ADBE Position"), scale = transform.property("ADBE Scale");
var rot = transform.property("ADBE Rotate Z"), anchor = transform.property("ADBE Anchor Point");
var doc = source.value;
if (!staticProp(source) || !staticProp(pos) || !staticProp(scale) || !staticProp(rot) ||
!staticProp(anchor) || pos.dimensionsSeparated || !doc.pointText || /[\r\n]/.test(doc.text) ||
!doc.text.length || text.property("ADBE Text Animators").numProperties) {
alert("Use single-line point text without keys, expressions, separated position or text animators."); return;
}
targets.push({layer:layer, source:source, pos:pos, before:layer.sourceRectAtTime(comp.time, false),
scale:scale.value, rotation:rot.value, position:pos.value, oldDoc:source.value});
}
app.beginUndoGroup("Change text alignment and compensate position");
try {
for (i = 0; i < targets.length; i++) {
var t = targets[i], doc = t.source.value;
doc.justification = TARGET; t.source.setValue(doc);
var after = t.layer.sourceRectAtTime(comp.time, false);
var dx = (t.before.left - after.left) * t.scale[0] / 100;
var dy = (t.before.top - after.top) * t.scale[1] / 100;
var angle = t.rotation * Math.PI / 180;
var x = t.position[0] + dx * Math.cos(angle) - dy * Math.sin(angle);
var y = t.position[1] + dx * Math.sin(angle) + dy * Math.cos(angle);
if (!isFinite(x) || !isFinite(y)) { throw new Error("Invalid bounds or position."); }
t.pos.setValue([x, y]);
}
} catch (error) {
alert("Stopped. Some text may have changed. Undo or reopen your practice copy.\n" + error);
} finally { app.endUndoGroup(); }
}());
sourceRectAtTimeで変更前後の矩形を読み、ローカル座標の差へX/Yスケールと回転を適用して位置に加えます。
例えば矩形のleftが0から−50へ変わり、スケール100%・回転0度なら、位置Xの補正量は+50です。
同じ差でXスケール200%なら+100、回転90度ならY方向へ+100の補正になる数値例です。
実際の矩形幅は文字・フォント・書式で変わるため、例の50をコードに固定していません。
右揃えはTARGETをParagraphJustification.RIGHT_JUSTIFY、左揃えはParagraphJustification.LEFT_JUSTIFYへ変更して使います。
段落テキスト、改行を含む文字、3D、親付き、自動方向、テキストアニメーター、位置の次元分割、対象のキーや既存式があると書き込み前に停止します。
位置・スケール・回転・アンカーポイント・ソーステキストは静的な値を使い、アニメーションを含む作品へそのまま適用しないでください。
輪郭や影などの効果を含む描画ピクセルの一致、縦組みや複雑な混在書式は未検証なので、単純な練習文字で確認します。
途中停止で揃えだけ変わった場合も、Ctrl+Z/Command+Zを1回実行して揃え・位置の両方を照合するか、練習コピーを開き直します。
コードの構文・数値計算・模擬APIを確認しましたが、AE本体での操作、描画、取り消しの実行確認は未完了です。
| 入力・条件 | 操作・結果 | 確認する点 |
|---|---|---|
| 1行・2D・親なし | 矩形差を位置で補正 | 文字の見た目と座標を照合 |
| Xスケール200%・回転90度 | 差50をYへ100補正 | 数値例は実機撮影ではない |
| キー・式・3D・段落 | 処理を開始しない | 対象条件を確認 |
参照:コミュニティ管理のsourceRectAtTimeとTextDocument。
資料確認日:2026年10月3日。
旧記事の途切れたfor文と、スケール・回転を考慮しない固定補正を置き換えました。
旧実装の参考コードはGitHubに残っていますが、本稿の修正版とは内容が異なります。
関連記事
対象の異なる操作は、以下の記事で確認できます。





