コモノExtendScript100本ノック

超初心者のDTPオペレーターが週にひとつスクリプトを書くブログ

053.【Id】アンカー付きオブジェクトのグループに別のアイテムを追加する

(元のアンカー付きオブジェクトはグループである必要はないのだけど、他に分かりやすい表現を見つけられなかった)

選択したオブジェクトに重なっているアンカー付きオブジェクトがあった場合、

  • 一旦アンカーを解除
  • 選択オブジェクトと元々アンカー付きオブジェクトだったオブジェクトをグループ化
  • 再度アンカー付きオブジェクトとして設定
  • 「元と全く同じ位置になるようにオフセット値を設定しますか?」というアラートが出るので任意で位置を変更

    書いたコード

var main = function() {
    app.scriptPreferences.enableRedraw = false;
    var doc = app.activeDocument;
    if (app.selection.length !== 1) {
        alert("オブジェクトを選択してください");
        exit();
    }
    if (!app.selection[0].hasOwnProperty("parentPage")) {
        alert("オブジェクトを選択してください");
        exit();
    }
    var sel = app.selection[0];
    var gb1 = sel.geometricBounds;
    var p = sel.parentPage;
    var aObjs = [];
    for (var i = 0; i < p.allPageItems.length; i++) {
        var obj = p.allPageItems[i];
        if (obj.parent.constructor.name === "Character") {
            aObjs.push(checkOverlap(sel, obj));
        }
    }
    if (aObjs.length !== 1) {
        alert("対象となるアンカー付きオブジェクトを特定できません");
        exit();
    }
    var aObj = aObjs[0];
    var gb2 = aObj.geometricBounds;
    var tmp = aObj.parent;
    var ip = aObj.parent.insertionPoints[0];
    app.select(ip);
    var pref = aObj.anchoredObjectSettings.properties;
    aObj.anchoredObjectSettings.releaseAnchoredObject();
    var grp = p.groups.add([aObj, sel]);
    var gb3 = grp.geometricBounds;
    grp.anchoredObjectSettings.insertAnchoredObject(ip, AnchorPosition.ANCHORED);
    grp.anchoredObjectSettings.properties = pref;
    if (confirm("元と全く同じ位置になるようにオフセット値を設定しますか?")) {
        // 基準を取得
        var ap = grp.anchoredObjectSettings.anchorPoint.toString();
        var diff = [
            gb2[0] - gb3[0],
            gb2[1] - gb3[1],
            gb3[2] - gb2[2],
            gb3[3] - gb2[3]
        ];
        if (/^[BOTTOM|TOP]/.test(ap)) {
            var v = ap.replace(/_.+$/, "");
        } else {
            var v = "CENTER";
        }
        if (v === "CENTER") {
            var h = ap.replace(/_.+$/, "");
        } else {
            var h = ap.split("_")[1];
        }
        switch (v) {
            case "TOP":
                grp.move(undefined, ["0mm", -(diff[0])]);
                break;
            case "BOTTOM":
                grp.move(undefined, ["0mm", diff[2]]);
                break;
            case "CENTER":
                grp.move(undefined, ["0mm", (diff[2] - (diff[0])) / 2]);
                break;
            default:
                alert("処理を中止します");
                app.undo();
                exit();
                break;
        }
        switch (h) {
            case "LEFT":
                grp.move(undefined, [-(diff[1]), "0mm"]);
                break;
            case "RIGHT":
                grp.move(undefined, [diff[3]], "0mm");
                break;
            case "CENTER":
                grp.move(undefined, [(diff[3] - (diff[1])) / 2, "0mm"]);
                break;
            default:
                alert("処理を中止します");
                app.undo();
                exit();
                break;
        }

    }

    function checkOverlap(tgt1, tgt2) {
        var gb1 = tgt1.geometricBounds;
        var gb2 = tgt2.geometricBounds;
        if (gb1[0] < gb2[2] && gb1[2] > gb2[0] && gb1[1] < gb2[3] && gb1[3] > gb2[1]) {
            return tgt2;
        }
    }
}

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.FAST_ENTIRE_SCRIPT, "アンカー付きオブジェクトに追加");

メモ

分かったこと

  • アンカー付きオブジェクトの位置を操作したいときはmove()を使う。geometricBoundsは効かない。
  • アンカー付きオブジェクトのparentはCharacterオブジェクト(おそらくアンカーポイント?)だが、insertAnchoredObjectメソッドのパラメータはinsertionPointオブジェクト。
  • InDesignの標準機能として、インライン/行の上オブジェクトではアンカーを解除することができない。