Amazonで商品を見るセール会場へ

Illustratorスクリプト(jsx)│レイヤー操作に関するスクリプトまとめ

IllustratorのJSXでレイヤーを取得・作成し、選択したオブジェクトを移動する処理例です。参照する階層を明示し、同じ階層の名前が重複している場合は処理を止めます。

2026年10月3日にコードと説明を改修しました。掲載例はコピーしたデータで試し、レイヤー構造、重なり順、外観、書き出し結果を確認してから使ってください。現在の改修版について、Illustratorでの動作確認はまだ完了していません。

目次

アクティブなレイヤーとオブジェクト選択の違い

doc.activeLayerは新しいオブジェクトを置く現在のレイヤーです。この値を変更しても、レイヤー内のオブジェクトをすべて選択する処理にはなりません。doc.selectionはオブジェクトなどの選択状態で、何も選んでいないときはnull、文字編集中は文字範囲を返す場合があります。

名前の取得は階層ごとに行う

最上位はdoc.layers、子はparent.layersを調べます。下のuniqueLayerは、渡されたコレクションだけを検索します。同名が0件または2件以上ならエラーにするため、名前でどれか1件を暗黙に選ぶ動作を避けられます。

取得する階層コード内の参照
最上位uniqueLayer(doc.layers, “親”)
親の直下uniqueLayer(parent.layers, “子”)
子の直下uniqueLayer(child.layers, “孫”)

最上位のレイヤーをアクティブにする

(function () {
  try {
    if (app.documents.length === 0) throw new Error("ドキュメントを開いてください。");
    var doc = app.activeDocument;
    var target = uniqueLayer(doc.layers, "親");
    requireEditable(target);
    doc.activeLayer = target;
  } catch (e) { alert(String(e)); }
function uniqueLayer(layers, name) {
  var found = null;
  for (var i = 0; i < layers.length; i++) {
    if (layers[i].name === name) {
      if (found !== null) throw new Error("同名レイヤーが複数あります: " + name);
      found = layers[i];
    }
  }
  if (found === null) throw new Error("レイヤーがありません: " + name);
  return found;
}
function requireEditable(node) {
  while (node && node.typename !== "Document") {
    if (node.locked || node.hidden || (node.typename === "Layer" && !node.visible))
      throw new Error("ロック・非表示の対象があります。");
    node = node.parent;
  }
}
}());

子・孫レイヤーをアクティブにする

(function () {
  try {
    if (app.documents.length === 0) throw new Error("ドキュメントを開いてください。");
    var doc = app.activeDocument;
    var parent = uniqueLayer(doc.layers, "親");
    var child = uniqueLayer(parent.layers, "子");
    var target = uniqueLayer(child.layers, "孫");
    requireEditable(target);
    doc.activeLayer = target;
  } catch (e) { alert(String(e)); }
function uniqueLayer(layers, name) {
  var found = null;
  for (var i = 0; i < layers.length; i++) {
    if (layers[i].name === name) {
      if (found !== null) throw new Error("同名レイヤーが複数あります: " + name);
      found = layers[i];
    }
  }
  if (found === null) throw new Error("レイヤーがありません: " + name);
  return found;
}
function requireEditable(node) {
  while (node && node.typename !== "Document") {
    if (node.locked || node.hidden || (node.typename === "Layer" && !node.visible))
      throw new Error("ロック・非表示の対象があります。");
    node = node.parent;
  }
}
}());

親レイヤーと子レイヤーを作成する

(function () {
  try {
    if (app.documents.length === 0) throw new Error("ドキュメントを開いてください。");
    var doc = app.activeDocument;
    for (var i = 0; i < doc.layers.length; i++) {
      if (doc.layers[i].name === "新しい親") throw new Error("同名の親が存在します。");
    }
    var parent = doc.layers.add();
    parent.name = "新しい親";
    var child = parent.layers.add();
    child.name = "新しい子";
  } catch (e) { alert(String(e)); }
function uniqueLayer(layers, name) {
  var found = null;
  for (var i = 0; i < layers.length; i++) {
    if (layers[i].name === name) {
      if (found !== null) throw new Error("同名レイヤーが複数あります: " + name);
      found = layers[i];
    }
  }
  if (found === null) throw new Error("レイヤーがありません: " + name);
  return found;
}
function requireEditable(node) {
  while (node && node.typename !== "Document") {
    if (node.locked || node.hidden || (node.typename === "Layer" && !node.visible))
      throw new Error("ロック・非表示の対象があります。");
    node = node.parent;
  }
}
}());

選択したオブジェクトを「まとめ」へ移動する

移動前に全件を検査し、選択を配列へ控えてから移します。グループ内の一部を直接取り出すと、クリッピングや親の外観から外れるため、この例では部分選択を拒否します。移動対象のロック・非表示を勝手に解除しません。

(function () {
  try {
    if (app.documents.length === 0) throw new Error("ドキュメントを開いてください。");
    var doc = app.activeDocument;
    var selection = doc.selection;
    if (!selection || !(selection instanceof Array) || selection.length === 0)
      throw new Error("選択ツールでオブジェクト全体を選んでください。");
    var target = uniqueLayer(doc.layers, "まとめ");
    requireEditable(target);
    var items = [];
    for (var i = 0; i < selection.length; i++) {
      var item = selection[i];
      if (!item || typeof item.move !== "function" || item.typename === "TextRange" || item.typename === "InsertionPoint")
        throw new Error("文字編集中など、対象外の選択です。");
      if (item.parent.typename !== "Layer")
        throw new Error("グループ内の部分選択は対象外です。グループ全体を選んでください。");
      requireEditable(item);
      items.push(item);
    }
    for (var j = items.length - 1; j >= 0; j--)
      items[j].move(target, ElementPlacement.PLACEATBEGINNING);
  } catch (e) { alert(String(e)); }
function uniqueLayer(layers, name) {
  var found = null;
  for (var i = 0; i < layers.length; i++) {
    if (layers[i].name === name) {
      if (found !== null) throw new Error("同名レイヤーが複数あります: " + name);
      found = layers[i];
    }
  }
  if (found === null) throw new Error("レイヤーがありません: " + name);
  return found;
}
function requireEditable(node) {
  while (node && node.typename !== "Document") {
    if (node.locked || node.hidden || (node.typename === "Layer" && !node.visible))
      throw new Error("ロック・非表示の対象があります。");
    node = node.parent;
  }
}
}());

配列の末尾から移動先の先頭へ入れるため、配列内の順序を反転させずに配置します。ただし、selectionの順序が元のレイヤーパネル全体の重なり順と一致する保証はありません。異なるレイヤー間の前後関係や、親レイヤーの効果・透明度は移動後に比較してください。途中でmoveが失敗すると一部だけ移動した状態が残ります。保存せず結果を確認します。

JSXの保存と実行

コードをUTF-8のテキストで保存し、拡張子を.jsxにします。「ファイル」→「スクリプト」→「その他のスクリプト」から選びます。保存・実行の詳しい手順はJSX入門を参照してください。各コードは別々のファイルとして実行します。

確認用の小さな例

  • 「親」の中に「子」、その中に「孫」を作り、各コードが指定した階層だけを参照するか確認する。
  • 同じ階層に「親」を2つ置き、変更前にエラーで停止するか確認する。
  • 「まとめ」をロック、非表示にし、解除せず停止するか確認する。
  • 別レイヤーの重なる図形とクリッピンググループで、移動前後の外観を比較する。

親だけを外す用途は子レイヤーを残して親を削除する処理、参照の基礎はDOMの階層へ進んでください。旧GitHub版・既存画像は今回の改修版と一致するとは限りません。

参照資料

Adobe公式のレイヤーパネル概要と、Adobe資料をもとに維持されているLayerのAPI参照を参照しました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメント一覧 (1件)

  • I am usually to running a blog and i actually respect your content. The article has actually peaks my interest. I am going to bookmark your website and preserve checking for brand new information.

コメントする

目次