【無料配布】Illustratorでトンボ・マージン・ガイドを一括作成するスクリプト|コピペで簡単導入

スポンサーリンク
素材・テンプレ
スポンサーリンク

Illustratorでチラシや名刺を作るたびに、

  • トンボを作る
  • 塗り足しを確認する
  • マージンガイドを引く

こんな作業を毎回手動で行っていませんか?

実はこの作業、スクリプトを使えば数秒で完了します。

特に印刷物を頻繁に制作するデザイナーにとって、トンボやガイド作成は避けて通れない定番作業。

とはいえ、毎回同じ操作を繰り返すのは正直面倒ですよね。

そこで今回は、Illustratorで

  • トンボ作成
  • 塗り足しガイド作成
  • マージンガイド作成

を一括で行えるスクリプトを無料公開します。

導入方法もコピペだけなので、Illustrator初心者の方でもすぐ利用できます。

トンボ・マージン・ガイド作成が面倒な理由

印刷物制作では、デザインそのものより準備作業に時間を取られることがあります。

特に以下は定番作業です。

  • トンボ作成
  • 塗り足し確認
  • マージン設定
  • ガイド作成

一つひとつは簡単ですが、案件数が増えるほど地味に時間を消費します。

さらに設定ミスがあると印刷事故につながるため、慎重な作業も必要です。

トンボマージンガイド作成セットとは?

今回公開するスクリプトは、選択したオブジェクトを基準に

  • トンボ
  • 塗り足しライン
  • マージンガイド

を一括生成するIllustrator用スクリプトです。

毎回同じ作業を繰り返す必要がなくなるため、作業効率が大幅に向上します。

スクリプトでできること

トンボ作成

仕上がりサイズを基準にトンボを自動生成。

印刷入稿用データ作成がスムーズになります。

塗り足しガイド作成

一般的な3mm塗り足しを想定したガイドを自動配置。

塗り足し忘れ防止にも役立ちます。

マージンガイド作成

文字切れ防止用の安全マージンを自動作成。

チラシや名刺制作で特に便利です。

スクリプトの導入方法

STEP1

以下のコードをすべてコピーします。

スポンサーリンク

#target illustrator
(function () {

    if (app.documents.length === 0) {
        alert("ドキュメントがありません");
        return;
    }

    var doc = app.activeDocument;
    var PT = 72 / 25.4;

    var LAYER_GUIDE = "guide";
    var LAYER_TONBO = "tonbo";
    var LAYER_OBJECT = "object";
    var LAYER_DOC_FILL = "document_fill";
    var LAYER_BLEED_FILL = "bleed_fill";

    var previewApplied = false;
    var suppressPreview = false;

    function mm(v) {
        return v * PT;
    }

    function num(v, d) {
        var n = parseFloat(String(v).replace(",", "."));
        return isNaN(n) ? d : n;
    }

    function int1(v, d) {
        var n = parseInt(v, 10);
        if (isNaN(n)) n = d;
        return Math.max(1, n);
    }

    function getLayer(name) {
        for (var i = 0; i < doc.layers.length; i++) {
            if (doc.layers[i].name === name) return doc.layers[i];
        }
        var l = doc.layers.add();
        l.name = name;
        return l;
    }

    function unlockLayerDeep(layer) {
        if (!layer) return;

        try { layer.locked = false; } catch (e) {}
        try { layer.visible = true; } catch (e2) {}
        try { layer.printable = true; } catch (e3) {}

        for (var i = 0; i < layer.layers.length; i++) {
            unlockLayerDeep(layer.layers[i]);
        }

        for (var j = 0; j < layer.pageItems.length; j++) {
            try { layer.pageItems[j].locked = false; } catch (e4) {}
            try { layer.pageItems[j].hidden = false; } catch (e5) {}
        }
    }

    function unlockAllLayers() {
        for (var i = 0; i < doc.layers.length; i++) {
            unlockLayerDeep(doc.layers[i]);
        }
    }

    function clearLayer(layer) {
        unlockLayerDeep(layer);
        try { doc.activeLayer = layer; } catch (e) {}

        for (var i = layer.pageItems.length - 1; i >= 0; i--) {
            try { layer.pageItems[i].remove(); } catch (e2) {}
        }
    }

    function removeLayer(name) {
        unlockAllLayers();
        for (var i = doc.layers.length - 1; i >= 0; i--) {
            if (doc.layers[i].name === name) {
                try { doc.layers[i].locked = false; } catch (e1) {}
                try { doc.layers[i].visible = true; } catch (e2) {}
                try { doc.layers[i].remove(); } catch (e3) {}
            }
        }
    }

    function makeRGB(r, g, b) {
        var c = new RGBColor();
        c.red = r;
        c.green = g;
        c.blue = b;
        return c;
    }

    function makeCMYK(c, m, y, k) {
        var col = new CMYKColor();
        col.cyan = c;
        col.magenta = m;
        col.yellow = y;
        col.black = k;
        return col;
    }

    function previewColor() {
        return makeRGB(0, 140, 255);
    }

    function docFillColor() {
        return makeCMYK(0, 0, 0, 15);
    }

    function bleedFillColor() {
        return makeCMYK(0, 100, 0, 0);
    }

    function previewRect(container, l, t, r, b) {
        var w = r - l;
        var h = t - b;
        if (w <= 0 || h <= 0) return null;

        var p = container.pathItems.rectangle(t, l, w, h);
        p.stroked = false;
        p.filled = true;
        p.fillColor = previewColor();
        try { p.opacity = 25; } catch (e) {}
        return p;
    }

    function fillRect(container, l, t, r, b, fillColor, opacity) {
        var w = r - l;
        var h = t - b;
        if (w <= 0 || h <= 0) return null;

        var p = container.pathItems.rectangle(t, l, w, h);
        p.stroked = false;
        p.filled = true;
        p.fillColor = fillColor;
        if (typeof opacity === "number") {
            try { p.opacity = opacity; } catch (e) {}
        }
        return p;
    }

    function guideRect(container, l, t, r, b) {
        var w = r - l;
        var h = t - b;
        if (w <= 0 || h <= 0) return null;

        var p = container.pathItems.rectangle(t, l, w, h);
        p.stroked = false;
        p.filled = false;
        p.guides = true;
        return p;
    }

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

    function getInnerRect(ab, s) {
        var L = ab[0], T = ab[1], R = ab[2], B = ab[3];

        var l = L + mm(s.marginLeft);
        var t = T - mm(s.marginTop);
        var r = R - mm(s.marginRight);
        var b = B + mm(s.marginBottom);

        return {
            l: l,
            t: t,
            r: r,
            b: b,
            w: r - l,
            h: t - b
        };
    }

    function buildCells(inner, cols, rows, gutterPt) {
        var totalGutterW = gutterPt * (cols - 1);
        var totalGutterH = gutterPt * (rows - 1);

        var cw = (inner.w - totalGutterW) / cols;
        var rh = (inner.h - totalGutterH) / rows;

        if (cw <= 0 || rh <= 0) return null;

        var xs = [], ys = [];

        var x = inner.l;
        for (var c = 0; c < cols; c++) {
            xs.push(x);
            x += cw + (c < cols - 1 ? gutterPt : 0);
        }

        var y = inner.t;
        for (var r = 0; r < rows; r++) {
            ys.push(y);
            y -= rh + (r < rows - 1 ? gutterPt : 0);
        }

        return {
            cw: cw,
            rh: rh,
            xs: xs,
            ys: ys
        };
    }

    function buildPreview(container, s) {
        var cols = int1(s.splitVertical, 1);
        var rows = int1(s.splitHorizontal, 1);
        var gutterPt = mm(Math.max(0, s.gutter));

        for (var a = 0; a < doc.artboards.length; a++) {
            var ab = doc.artboards[a].artboardRect;
            var inner = getInnerRect(ab, s);

            if (inner.w <= 0 || inner.h <= 0) continue;

            var grid = buildCells(inner, cols, rows, gutterPt);
            if (!grid) continue;

            for (var rr = 0; rr < rows; rr++) {
                for (var cc = 0; cc < cols; cc++) {
                    var l = grid.xs[cc];
                    var t = grid.ys[rr];
                    var r = l + grid.cw;
                    var b = t - grid.rh;
                    previewRect(container, l, t, r, b);
                }
            }
        }
    }

    function buildGuide(container, s) {
        var mt = mm(s.marginTop);
        var mr = mm(s.marginRight);
        var mb = mm(s.marginBottom);
        var ml = mm(s.marginLeft);

        var cols = int1(s.splitVertical, 1);
        var rows = int1(s.splitHorizontal, 1);
        var gut = mm(Math.max(0, s.gutter));
        var mode = s.mode;

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

            var l = L + ml;
            var t = T - mt;
            var r = R - mr;
            var b = B + mb;

            var W = r - l;
            var H = t - b;
            if (W <= 0 || H <= 0) continue;

            guideRect(container, l, t, r, b);

            var cw = (W - gut * (cols - 1)) / cols;
            var rh = (H - gut * (rows - 1)) / rows;

            if (cw <= 0 || rh <= 0) continue;

            for (var c = 1; c < cols; c++) {
                var gx = l + (cw * c) + (gut * (c - 1));
                if (mode === "center") {
                    guideLine(container, gx + gut / 2, t, gx + gut / 2, b);
                } else {
                    guideLine(container, gx, t, gx, b);
                    guideLine(container, gx + gut, t, gx + gut, b);
                }
            }

            for (var r2 = 1; r2 < rows; r2++) {
                var gy = t - (rh * r2) - (gut * (r2 - 1));
                if (mode === "center") {
                    guideLine(container, l, gy - gut / 2, r, gy - gut / 2);
                } else {
                    guideLine(container, l, gy, r, gy);
                    guideLine(container, l, gy - gut, r, gy - gut);
                }
            }
        }
    }

    function buildDocumentFill(container, s) {
        var fillCol = docFillColor();

        for (var a = 0; a < doc.artboards.length; a++) {
            var ab = doc.artboards[a].artboardRect;
            fillRect(container, ab[0], ab[1], ab[2], ab[3], fillCol, 100);
        }
    }

    function buildBleedFill(container, s) {
        var bleedPt = mm(Math.max(0, s.bleed));
        var fillCol = bleedFillColor();

        for (var a = 0; a < doc.artboards.length; a++) {
            var ab = doc.artboards[a].artboardRect;

            var l = ab[0] - bleedPt;
            var t = ab[1] + bleedPt;
            var r = ab[2] + bleedPt;
            var b = ab[3] - bleedPt;

            fillRect(container, l, t, r, b, fillCol, 100);
        }
    }

    function makeTrim(layer, ab) {
        unlockAllLayers();
        unlockLayerDeep(layer);
        try { doc.activeLayer = layer; } catch (e) {}

        var prevLayer = doc.activeLayer;
        var prevSel = doc.selection;

        doc.selection = null;

        var r = layer.pathItems.rectangle(
            ab[1],
            ab[0],
            ab[2] - ab[0],
            ab[1] - ab[3]
        );

        r.stroked = false;
        r.filled = false;
        r.selected = true;

        var ran = false;
        try { app.executeMenuCommand("TrimMark v25"); ran = true; } catch (e1) {}
        if (!ran) {
            try { app.executeMenuCommand("TrimMark"); ran = true; } catch (e2) {}
        }
        if (!ran) {
            try { app.executeMenuCommand("trimMarks"); ran = true; } catch (e3) {}
        }

        try { r.remove(); } catch (e4) {}

        doc.selection = null;
        try { doc.activeLayer = prevLayer; } catch (e5) {}
        try { doc.selection = prevSel; } catch (e6) {}

        if (!ran) {
            throw new Error("Illustrator のトリムマーク作成コマンドを実行できませんでした");
        }
    }

    function clearPreview() {
        if (!previewApplied) {
            clearLayer(getLayer(LAYER_OBJECT));
            return;
        }

        suppressPreview = true;
        try { app.undo(); } catch (e) {}
        previewApplied = false;
        suppressPreview = false;

        var objectLayer = getLayer(LAYER_OBJECT);
        clearLayer(objectLayer);
    }

    function renderPreview(s) {
        clearPreview();

        var layer = getLayer(LAYER_OBJECT);
        layer.locked = false;
        layer.visible = true;
        clearLayer(layer);

        buildPreview(layer, s);

        try { layer.zOrder(ZOrderMethod.BRINGTOFRONT); } catch (e) {}
        previewApplied = true;
        app.redraw();
    }

    function finalizeObjectLayer(keepObjectLayer) {
        var objectLayer = getLayer(LAYER_OBJECT);
        clearLayer(objectLayer);

        if (!keepObjectLayer) {
            removeLayer(LAYER_OBJECT);
        } else {
            try { objectLayer.locked = false; } catch (e1) {}
            try { objectLayer.visible = true; } catch (e2) {}
        }
    }

    function apply(s) {
        clearPreview();

        var g = getLayer(LAYER_GUIDE);
        var t = getLayer(LAYER_TONBO);

        clearLayer(g);
        clearLayer(t);

        buildGuide(g, s);

        if (s.trim) {
            for (var i = 0; i < doc.artboards.length; i++) {
                makeTrim(t, doc.artboards[i].artboardRect);
            }
        }

        if (s.addDocFill) {
            var dLayer = getLayer(LAYER_DOC_FILL);
            clearLayer(dLayer);
            buildDocumentFill(dLayer, s);
            try { dLayer.locked = false; } catch (e10) {}
            try { dLayer.zOrder(ZOrderMethod.SENDTOBACK); } catch (e11) {}
        } else {
            removeLayer(LAYER_DOC_FILL);
        }

        if (s.addBleedFill) {
            var bLayer = getLayer(LAYER_BLEED_FILL);
            clearLayer(bLayer);
            buildBleedFill(bLayer, s);
            try { bLayer.locked = false; } catch (e12) {}
            try { bLayer.zOrder(ZOrderMethod.SENDTOBACK); } catch (e13) {}
        } else {
            removeLayer(LAYER_BLEED_FILL);
        }

        try { g.locked = true; } catch (e1) {}
        try { t.locked = true; } catch (e2) {}

        try { g.zOrder(ZOrderMethod.BRINGTOFRONT); } catch (e3) {}
        try { t.zOrder(ZOrderMethod.BRINGTOFRONT); } catch (e4) {}

        finalizeObjectLayer(s.keepObjectLayer);
        previewApplied = false;

        app.redraw();
    }

    var w = new Window("dialog", "ガイド作成");
    w.orientation = "column";
    w.alignChildren = ["fill", "top"];
    w.spacing = 8;
    w.margins = 12;

    var pMargin = w.add("panel", undefined, "マージン");
    pMargin.orientation = "column";
    pMargin.alignChildren = ["left", "center"];
    pMargin.margins = 10;

    var g1 = pMargin.add("group");
    g1.add("statictext", undefined, "上");
    var edTop = g1.add("edittext", undefined, "10");
    edTop.characters = 5;
    g1.add("statictext", undefined, "右");
    var edRight = g1.add("edittext", undefined, "10");
    edRight.characters = 5;

    var g2 = pMargin.add("group");
    g2.add("statictext", undefined, "下");
    var edBottom = g2.add("edittext", undefined, "10");
    edBottom.characters = 5;
    g2.add("statictext", undefined, "左");
    var edLeft = g2.add("edittext", undefined, "10");
    edLeft.characters = 5;

    var pDiv = w.add("panel", undefined, "分割");
    pDiv.orientation = "column";
    pDiv.alignChildren = ["left", "center"];
    pDiv.margins = 10;

    var g3 = pDiv.add("group");
    g3.add("statictext", undefined, "縦");
    var edCols = g3.add("edittext", undefined, "2");
    edCols.characters = 5;
    g3.add("statictext", undefined, "横");
    var edRows = g3.add("edittext", undefined, "2");
    edRows.characters = 5;

    var g4 = pDiv.add("group");
    g4.add("statictext", undefined, "間隔");
    var edGutter = g4.add("edittext", undefined, "10");
    edGutter.characters = 6;
    g4.add("statictext", undefined, "mm");

    var g5 = pDiv.add("group");
    g5.add("statictext", undefined, "方式");
    var ddMode = g5.add("dropdownlist", undefined, ["ガター中央(1本)", "カラム境界(左右2本)"]);
    ddMode.selection = 0;

    var pTrim = w.add("panel", undefined, "トリムマーク");
    pTrim.orientation = "column";
    pTrim.alignChildren = ["left", "center"];
    pTrim.margins = 10;

    var g6 = pTrim.add("group");
    g6.add("statictext", undefined, "ブリード");
    var edBleed = g6.add("edittext", undefined, "3");
    edBleed.characters = 6;
    g6.add("statictext", undefined, "mm");

    var cbTrim = pTrim.add("checkbox", undefined, "トリムマーク作成(Illustrator 純正)");
    cbTrim.value = true;

    var pFill = w.add("panel", undefined, "塗りオブジェクト");
    pFill.orientation = "column";
    pFill.alignChildren = ["left", "top"];
    pFill.margins = 10;

    var cbDocFill = pFill.add("checkbox", undefined, "ドキュメントサイズのオブジェクトを追加");
    cbDocFill.value = false;

    var cbBleedFill = pFill.add("checkbox", undefined, "塗りたしサイズのオブジェクトを追加");
    cbBleedFill.value = false;

    var note = pFill.add("statictext", undefined, "※ 塗りは固定色です(ドキュメント=K15 / 塗りたし=M100)");
    note.enabled = true;

    var pPreview = w.add("panel", undefined, "プレビュー object レイヤー");
    pPreview.orientation = "column";
    pPreview.alignChildren = ["left", "top"];
    pPreview.margins = 10;

    var cbPreview = pPreview.add("checkbox", undefined, "プレビュー表示(object レイヤーに表示)");
    cbPreview.value = true;

    var cbKeepObject = pPreview.add("checkbox", undefined, "OK後も object レイヤーを残す");
    cbKeepObject.value = false;

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

    function getS() {
        return {
            marginTop: num(edTop.text, 10),
            marginRight: num(edRight.text, 10),
            marginBottom: num(edBottom.text, 10),
            marginLeft: num(edLeft.text, 10),
            splitVertical: int1(edCols.text, 2),
            splitHorizontal: int1(edRows.text, 2),
            gutter: num(edGutter.text, 0),
            mode: (ddMode.selection && ddMode.selection.index === 1) ? "edge" : "center",
            bleed: num(edBleed.text, 3),
            trim: cbTrim.value,
            addDocFill: cbDocFill.value,
            addBleedFill: cbBleedFill.value,
            keepObjectLayer: cbKeepObject.value
        };
    }

    function upd() {
        if (suppressPreview) return;
        if (!cbPreview.value) {
            clearPreview();
            return;
        }
        renderPreview(getS());
    }

    edTop.onChanging = upd;
    edRight.onChanging = upd;
    edBottom.onChanging = upd;
    edLeft.onChanging = upd;
    edCols.onChanging = upd;
    edRows.onChanging = upd;
    edGutter.onChanging = upd;
    edBleed.onChanging = upd;

    ddMode.onChange = upd;
    cbTrim.onClick = upd;
    cbPreview.onClick = upd;
    cbDocFill.onClick = upd;
    cbBleedFill.onClick = upd;
    cbKeepObject.onClick = upd;

    btnOK.onClick = function () {
        try {
            apply(getS());
            w.close();
        } catch (e) {
            alert(e.message);
        }
    };

    btnCancel.onClick = function () {
        clearPreview();
        removeLayer(LAYER_OBJECT);
        w.close();
    };

    w.onClose = function () {
        clearPreview();
        removeLayer(LAYER_OBJECT);
    };

    w.center();
    w.show();
    upd();

})();

STEP2

テキストエディタを開きます。

おすすめは以下。

  • VSCode
  • サクラエディタ
  • メモ帳

STEP3

ファイル名を

TomboMarginGuide.jsx

として保存します。

文字コードはUTF-8推奨です。

STEP4

Illustratorのスクリプトフォルダへ保存します。

Windows

Program Files/Adobe Illustrator/Presets/ja_JP/スクリプト

Mac

Applications/Adobe Illustrator/Presets.localized/ja_JP/スクリプト

保存後Illustratorを再起動してください。

使い方

  1. オブジェクトを選択
  2. ファイル
  3. スクリプト
  4. トンボマージンガイド作成セット
  5. 実行

これだけで完了です。

以下のようなウインドウが出てきて、マージンの数値や数が設定できます。

実際に使ってみた感想

私自身、チラシや販促物を制作することが多いのですが、このスクリプトを作ってからは毎回の下準備がかなり楽になりました。

ガイドも作成済みで始めることが出来るので、すぐに制作に取り掛かれますよ。

まとめ

Illustratorで印刷物を制作するなら、トンボやマージンガイド作成は避けて通れません。

だからこそ、自動化できる部分は自動化するのがおすすめです。

今回公開した「トンボマージンガイド作成セット」を使えば、

  • 作業時間短縮
  • ミス削減
  • 入稿品質向上

につながります。

ぜひコピペして使ってみてください。

スポンサーリンク

コメント