Illustratorでドキュメント上にあるたくさんの素材データをそれぞれアートボードに分割し、パスを軽くするワークフロー

発売して一ヶ月で3刷になっている書籍『WebデザインプロセスBook』の著者である加藤千歳さんにセミナーをお願いしました。

加藤千歳さんといえば、チェックバックに自筆で書き込まれる独特のスタイルが印象的です。

アンケート特典として「手書き素材」をご用意いただきました。

Illustratorのベクターデータで提供いただいているのですが、ほかのアプリにコピー&ペーストしたり、配置するときなどに、手をかけたいかもと思いつつ、アクションを活用したとしてもクラクラする膨大な量です。

  • 線はアウトライン化したい

  • 少しでもパスを軽くしたい

  • 素材ごとに別のアートボードになっているとよいかも(個別のIllustratorファイルに分割しやすいし)

同様に、1つのIllustratorドキュメントにたくさんの素材データがまとまって送られてくることがあるため、ドキュメント上にあるたくさんの素材データをそれぞれアートボードに分割し、パスを軽くするワークフローについて考えてみました。


1 | 隣接しているオブジェクトをグループ化し、それぞれをアートボードに変換

ChatGPTとのやりとりで次のスクリプトができました。

/**
 * スクリプト名: ReplaceArtboardsWithGroups.jsx
 * 作成日:2024-11-19
 * 修正版:クリップグループの見た目の大きさを基準にアートボードを作成
 */

// アクティブドキュメントを取得
var doc = app.activeDocument;

// アートボード上のすべてのオブジェクトを取得
var allObjects = doc.pageItems;

// 対象オブジェクトがない場合は終了
if (allObjects.length === 0) {
    alert("アートボード上にオブジェクトがありません。");
} else {
    // グループ化するための配列
    var groupedObjects = [];

    // 全てのオブジェクトを調べる
    for (var i = 0; i < allObjects.length; i++) {
        var objA = allObjects[i];

        // グループ化されたかどうかのフラグ
        var isGrouped = false;

        for (var j = 0; j < groupedObjects.length; j++) {
            var group = groupedObjects[j];

            for (var k = 0; k < group.length; k++) {
                var objB = group[k];

                // オブジェクトAとBが重なっているか確認
                if (isOverlapping(objA, objB)) {
                    group.push(objA);
                    isGrouped = true;
                    break;
                }
            }

            if (isGrouped) {
                break;
            }
        }

        // グループ化されていなければ新しいグループを作成
        if (!isGrouped) {
            groupedObjects.push([objA]);
        }
    }

    // 新しいアートボードを作成
    for (var i = 0; i < groupedObjects.length; i++) {
        var newGroup = doc.groupItems.add(); // 新しいグループを作成

        for (var j = 0; j < groupedObjects[i].length; j++) {
            var currentItem = groupedObjects[i][j];

            if (currentItem.typename === "GroupItem" && currentItem.clipped) {
                // クリップグループをそのまま新しいグループに移動
                moveClipGroup(currentItem, newGroup);
            } else {
                // 通常のオブジェクトをグループに移動
                currentItem.move(newGroup, ElementPlacement.PLACEATEND);
            }
        }

        // グループの見た目の境界を取得(クリップパスの境界を基準)
        var groupBounds = getClippingBounds(newGroup);

        // アートボードを追加(見た目の境界を使用)
        doc.artboards.add([
            groupBounds[0],     // 左 (x1)
            groupBounds[1],     // 上 (y1)
            groupBounds[2],     // 右 (x2)
            groupBounds[3]      // 下 (y2)
        ]);
    }

    // 元のアートボードを削除
    while (doc.artboards.length > groupedObjects.length) {
        doc.artboards[0].remove(); // 最初のアートボードを削除
    }

    alert("すべてのオブジェクトをグループ化し、各グループをアートボードに変換しました。元のアートボードは削除されました。");
}

/**
 * オブジェクト同士が重なっているかを判定する関数
 * @param {PageItem} objA - オブジェクトA
 * @param {PageItem} objB - オブジェクトB
 * @returns {boolean} - 重なっている場合はtrue
 */
function isOverlapping(objA, objB) {
    // オブジェクトの境界を取得
    var boundsA = objA.visibleBounds; // プレビュー境界を使用
    var boundsB = objB.visibleBounds; // プレビュー境界を使用

    // AとBの境界を比較して重なっているかを確認
    return !(boundsA[2] < boundsB[0] || // AがBの左にある
             boundsA[0] > boundsB[2] || // AがBの右にある
             boundsA[1] < boundsB[3] || // AがBの上にある
             boundsA[3] > boundsB[1]);  // AがBの下にある
}

/**
 * クリップグループを新しいグループに移動する関数
 * @param {GroupItem} clipGroup - クリップグループ
 * @param {GroupItem} targetGroup - 移動先のグループ
 */
function moveClipGroup(clipGroup, targetGroup) {
    // クリップグループ全体を新しい親グループに移動
    var clonedClipGroup = clipGroup.duplicate(targetGroup, ElementPlacement.PLACEATEND);

    // 元のクリップグループを削除(必要に応じてコメントアウト可能)
    clipGroup.remove();
}

/**
 * グループ内のクリッピングパスの境界を取得
 * @param {GroupItem} group - グループアイテム
 * @returns {Array} - 境界の配列 [x1, y1, x2, y2]
 */
function getClippingBounds(group) {
    for (var i = 0; i < group.pageItems.length; i++) {
        var item = group.pageItems[i];
        if (item.clipping) {
            return item.visibleBounds; // クリップパスの境界を返す
        }
    }
    return group.visibleBounds; // クリップパスがない場合は通常の境界
}
  • クリップグループ利用時、アートボードの大きさが見た目になりません。

2 | 分割・拡張

線はアウトライン化して塗りにしたいので、いずれかを実行します。

  • [オブジェクト]メニューの[分割・拡張]

  • [オブジェクト]メニューの[パス]→[パスのアウトライン]

3 | ここで微調整

意図せず、グループ化されていたり、しなかったり、複合パスが外れてしまっていたりなどがありますので、微調整を行い、最初のスクリプトを再実行します。

4 | パスファインダー:合体

[パスファインダー]パネルの〈合体〉はスクリプトでは実行できません(アクションならできます)。

幸い、すべてグループ化されているので、[パスファインダー(合体)]効果を実行後、〈アピアランスを分割〉でいけそうです。

try {
    app.executeMenuCommand("Live Pathfinder Add");
    app.executeMenuCommand("expandStyle");
} catch (e) {
    alert("エラーが発生しました: " + e.message);
}

5 | パスの単純化

[パスの単純化]を実行して、アンカーポイントを減らします。
「自動」設定でもよい感じに仕上がります。

まとめ

4分ちょいで完了できますので優秀だと思いますが、ステップ2、ステップ3,ステップ4あたりは、もう少し自動化したいところです。

よいアイデアがあれば、ぜひ教えてください!

検討したアイデア

よそいちさんのスクリプト

今回の場合、グループ化する事前準備が煩雑です。

宮澤さんのスクリプト

今回の場合、それぞれの背景に長方形を作成する事前準備が煩雑です。

ご参考

「隣接しているものを探す」ではなく、「離れていたら…」のアプローチです。


ダウンロード

ここから先は

27字 / 3ファイル
月に10-20本くらいの記事を投稿しています。定期購読されると、更新のお知らせを受け取ったり、マガジン限定記事やサンプルファイルをダウンロードできます。 購読を開始した月に更新された記事から読むことができます(初月無料)。

DTP Transit 定期購読マガジン

¥100 / 月 初月無料

マガジン限定記事やサンプルファイルをダウンロードできます。

定期マガジンを購読されるとサンプルファイルをダウンロードいただけます。 https://note.com/dtp_tranist/m/mebd7eab21ea5