アートボードまたぎのガイドが邪魔すぎる…を一発解決するIllustratorスクリプト

スポンサーリンク
スクリプト
スポンサーリンク

Illustratorで複数アートボードを並べて作業していると、

「ガイドが隣のアートボードまで伸びて邪魔…」

ということ、ありませんか?

特にバナーやSNS画像を複数サイズで作っていると、横長・縦長のガイドがアートボードをまたいで表示されて、かなり見づらくなります。

そこで今回は、選択したガイドをアクティブアートボード内にピタッと収めるIllustratorスクリプトを紹介します。

ダウンロード形式ではなく、コードをコピーして自分で保存する方法で使えます。

Illustratorでアートボードまたぎのガイドが邪魔になる理由

Illustratorのガイドは、基本的にオブジェクトとして扱われます。

そのため、複数アートボードを並べていると、長く引いたガイドが他のアートボードまで伸びてしまうことがあります。

よくあるのはこんなケースです。

  • 複数サイズのバナーを同時に作っている
  • SNS画像をまとめて制作している
  • アートボードを横並びにしている
  • 中央揃え用のガイドが隣まで伸びる
  • 余白確認用のガイドが画面を横断する

地味ですが、実務ではかなりストレスです。

このスクリプトでできること

このスクリプトでは、選択したガイドを現在表示しているアクティブアートボード内の長さに調整できます。

できることは以下です。

  • 横ガイドをアートボードの左右いっぱいに収める
  • 縦ガイドをアートボードの上下いっぱいに収める
  • 隣のアートボードまではみ出たガイドを整理できる
  • 選択したガイドだけ処理できる

つまり、不要に長くなったガイドを一発でスッキリできます。

Illustratorスクリプトのコード

以下のコードをコピーして使ってください。


// #target illustrator
(function () {
    if (app.documents.length === 0) { alert("ドキュメントがありません"); return; }
    var doc = app.activeDocument;

    function mm2pt(mm){ return mm * 2.834645669; }
    function toNum(s, def){
        s = String(s).replace(",", ".").replace(/^\s+|\s+$/g, "");
        if (s === "") return def;
        var n = parseFloat(s);
        return isNaN(n) ? def : n;
    }

    function getGuideOrientation(pathItem){
        // "h" / "v" / "other"
        try{
            var pts = pathItem.pathPoints;
            if (!pts || pts.length < 2) return "other";
            var a = pts[0].anchor;
            var b = pts[pts.length-1].anchor;
            var dx = Math.abs(a[0]-b[0]);
            var dy = Math.abs(a[1]-b[1]);
            var eps = 0.01; // pt
            if (dy < eps && dx > eps) return "h";
            if (dx < eps && dy > eps) return "v";
        }catch(e){}
        return "other";
    }

    function getLineRange(pathItem, ori){
        // returns {min,max,const} in pt: for h => x-range + y const, for v => y-range + x const
        try{
            var pts = pathItem.pathPoints;
            var min = null, max = null, cst = null;
            for (var i=0;i<pts.length;i++){
                var a = pts[i].anchor;
                if (ori === "h"){
                    var x = a[0], y = a[1];
                    cst = (cst === null) ? y : cst;
                    min = (min === null) ? x : Math.min(min, x);
                    max = (max === null) ? x : Math.max(max, x);
                } else if (ori === "v"){
                    var x2 = a[0], y2 = a[1];
                    cst = (cst === null) ? x2 : cst;
                    min = (min === null) ? y2 : Math.min(min, y2);
                    max = (max === null) ? y2 : Math.max(max, y2);
                }
            }
            if (min === null || max === null || cst === null) return null;
            return { min:min, max:max, cst:cst };
        }catch(e){}
        return null;
    }

    function makeGuideLine(layer, x1,y1,x2,y2){
        var ln = layer.pathItems.add();
        ln.setEntirePath([[x1,y1],[x2,y2]]);
        ln.stroked = false;
        ln.filled = false;
        ln.guides = true;
        return ln;
    }

    function overlaps1D(a1,a2,b1,b2){
        // ranges can be reversed; normalize
        var amin = Math.min(a1,a2), amax = Math.max(a1,a2);
        var bmin = Math.min(b1,b2), bmax = Math.max(b1,b2);
        return (amax >= bmin) && (bmax >= amin);
    }

    function clamp(val, lo, hi){
        return Math.max(lo, Math.min(hi, val));
    }

    // ===== UI =====
    var w = new Window("dialog", "ガイドをアートボードごとに分割");
    w.orientation = "column";
    w.alignChildren = ["fill","top"];

    var g1 = w.add("group");
    g1.add("statictext", undefined, "アートボード外へ延長(mm)");
    var edExt = g1.add("edittext", undefined, "2");
    edExt.characters = 6;

    var cbSelectedOnly = w.add("checkbox", undefined, "選択中のガイドのみ(未選択なら全ガイド)");
    cbSelectedOnly.value = true;

    var cbDeleteOriginal = w.add("checkbox", undefined, "元のガイドを削除");
    cbDeleteOriginal.value = true;

    var btns = w.add("group"); btns.alignment = "right";
    var ok = btns.add("button", undefined, "OK");
    var cancel = btns.add("button", undefined, "Cancel");

    cancel.onClick = function(){ w.close(0); };

    ok.onClick = function(){
        var extPt = mm2pt(Math.max(0, toNum(edExt.text, 2)));

        // 対象ガイド取得
        var targets = [];
        if (cbSelectedOnly.value && doc.selection && doc.selection.length){
            for (var i=0;i<doc.selection.length;i++){
                var it = doc.selection[i];
                if (it.typename === "PathItem"){
                    try { if (it.guides === true) targets.push(it); } catch(e){}
                }
            }
        }
        if (targets.length === 0){
            // 全ガイド
            for (var li=0; li<doc.layers.length; li++){
                var lyr = doc.layers[li];
                // ざっくり:レイヤー直下のpathItemsのみ(多くはこれで十分)
                // (必要なら再帰版も作れます)
                for (var pi=0; pi<lyr.pathItems.length; pi++){
                    var p = lyr.pathItems[pi];
                    try { if (p.guides === true) targets.push(p); } catch(e2){}
                }
            }
        }

        if (targets.length === 0){
            alert("対象のガイドが見つかりませんでした");
            w.close(1);
            return;
        }

        // 分割処理
        var created = 0, removed = 0, skipped = 0;

        // 先に参照を配列化(削除しながら回すので)
        var snapshot = [];
        for (var t=0; t<targets.length; t++) snapshot.push(targets[t]);

        for (var t2=0; t2<snapshot.length; t2++){
            var g = snapshot[t2];
            var ori = getGuideOrientation(g);
            if (ori !== "h" && ori !== "v") { skipped++; continue; }

            var rng = getLineRange(g, ori);
            if (!rng) { skipped++; continue; }

            var ownerLayer;
            try { ownerLayer = g.layer; } catch(e3){ skipped++; continue; }

            // そのガイドが「どのアートボードを通るか」判定し、各AB分の区間を作る
            var touched = 0;

            for (var ai=0; ai<doc.artboards.length; ai++){
                var r = doc.artboards[ai].artboardRect; // [L,T,R,B]
                var L = r[0], T = r[1], R = r[2], B = r[3];

                if (ori === "h"){
                    var y = rng.cst;
                    // yがABの縦範囲内か
                    if (!(y <= T && y >= B)) continue;

                    // 元ガイドのx範囲と、ABの横範囲(±延長)が重なるか
                    var segL = L - extPt;
                    var segR = R + extPt;
                    if (!overlaps1D(rng.min, rng.max, segL, segR)) continue;

                    // ただし元の線分が短い場合は、その範囲に収める
                    var x1 = clamp(segL, Math.min(rng.min, rng.max), Math.max(rng.min, rng.max));
                    var x2 = clamp(segR, Math.min(rng.min, rng.max), Math.max(rng.min, rng.max));
                    if (Math.abs(x2 - x1) < 0.01) continue;

                    makeGuideLine(ownerLayer, x1, y, x2, y);
                    created++;
                    touched++;
                } else {
                    var x = rng.cst;
                    // xがABの横範囲内か
                    if (!(x >= L && x <= R)) continue;

                    // 元ガイドのy範囲と、ABの縦範囲(±延長)が重なるか
                    var segT = T + extPt;
                    var segB = B - extPt;
                    if (!overlaps1D(rng.min, rng.max, segB, segT)) continue;

                    var y1 = clamp(segT, Math.min(rng.min, rng.max), Math.max(rng.min, rng.max));
                    var y2 = clamp(segB, Math.min(rng.min, rng.max), Math.max(rng.min, rng.max));
                    if (Math.abs(y2 - y1) < 0.01) continue;

                    makeGuideLine(ownerLayer, x, y1, x, y2);
                    created++;
                    touched++;
                }
            }

            // 1つ以上のABに触れた = “またぎ” だった可能性が高いので、元削除(設定時)
            if (touched > 0 && cbDeleteOriginal.value){
                try { g.remove(); removed++; } catch(e4){}
            }
        }

        alert(
            "完了\n" +
            "作成: " + created + "\n" +
            "削除: " + removed + "\n" +
            "スキップ(斜め等): " + skipped
        );

        w.close(1);
    };

    w.center();
    w.show();
})();
  

スポンサーリンク

スクリプトの保存方法

このスクリプトは、ダウンロード不要です。

コピーしてテキストファイルとして保存すれば使えます。

手順

  1. 上のコードをすべてコピーする
  2. メモ帳やテキストエディタを開く
  3. コピーしたコードを貼り付ける
  4. ファイル名を付けて保存する

    例:guide_fit_artboard.jsx
  5. 拡張子を .jsx にする

Windowsのメモ帳で保存する場合は、ファイル名を

guide_fit_artboard.jsx

のようにして、文字コードはできれば UTF-8 にしておくと安心です。

Illustratorでスクリプトを実行する方法

保存したスクリプトは、Illustratorから実行できます。

手順

  1. Illustratorでファイルを開く
  2. 収めたいガイドを選択する
  3. 対象のアートボードをアクティブにする
  4. 上部メニューの

    ファイル > スクリプト > その他のスクリプト を選ぶ
  5. 保存した .jsx ファイルを選択する
  6. ガイドがアートボード内に収まる

ショートカット化したい場合は、アクションに登録しておくとさらに便利です。

使う前の注意点

このスクリプトを使う前に、以下を確認してください。

  • ガイドがロックされていると選択できない
  • 斜めのガイドには非対応
  • 曲線ガイドには非対応
  • 選択したガイドだけが処理対象
  • アクティブアートボードを基準に処理される

特に注意したいのは、どのアートボードがアクティブになっているかです。

違うアートボードがアクティブだと、意図しない位置にガイドが収まることがあります。

ガイドを選択できないときの対処法

ガイドが選択できない場合は、以下を確認してください。

ガイドがロックされている

上部メニューから、

表示 > ガイド > ガイドをロック

のチェックを外してください。

レイヤーがロックされている

レイヤーパネルで、対象レイヤーに鍵マークが付いていないか確認します。

鍵マークがある場合は、ロックを解除してください。

ガイドが非表示になっている

ガイドが見えない場合は、

表示 > ガイド > ガイドを表示

を選びます。

どんな作業で便利?

このスクリプトは、特に以下のような作業で便利です。

  • バナーを複数サイズで作るとき
  • Instagram投稿画像をまとめて作るとき
  • LP用パーツを複数アートボードで管理するとき
  • ロゴ案を横並びで比較するとき
  • 印刷物の表面・裏面を同じファイルで作るとき

ガイドが整理されるだけで、作業画面がかなり見やすくなります。

地味ですが、こういう小さなストレスを減らすと、デザイン作業はかなり快適になります。

まとめ

Illustratorで複数アートボードを使っていると、ガイドがアートボードをまたいで邪魔になることがあります。

今回紹介したスクリプトを使えば、選択したガイドをアクティブアートボード内に一発で収められます。

ポイントは以下です。

  • ガイドを選択してから実行する
  • アクティブアートボードを基準に処理される
  • 横ガイド・縦ガイドに対応
  • コードをコピーして .jsx で保存すれば使える

複数アートボードで作業する人には、かなり便利な時短スクリプトです。

スポンサーリンク

コメント