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参照を参照しました。

コメント
コメント一覧 (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.