Skip to main content
Inspiring
October 27, 2023
Answered

【Javascript】特定のレイヤーを削除するスクリプト

  • October 27, 2023
  • 2 replies
  • 1394 views

お世話になっております。

 

var layers = app.activeDocument.layers;

    for(j=0; j<layers.length; j++){

        if(layers[j].name == 'あいう' || layers[j].name == 'えおか' ||layers[j].name == 'きくけ' || layers[j].name == 'こさし' || layers[j].name == 'すせそ' || layers[j].name == 'たちつ'|| layers[j].name == 'てとな' || layers[j].name == 'にぬね' || layers[j].name == 'のはひ') {
            layers[j].remove();
        }
    }

 

こんなスクリプトがあったとします。

特定の名前のレイヤーがあったら削除するというものですが、削除したいレイヤーが大量にあって、多分ですが長すぎてスクリプトがうまく動作しませんでした。

 

一つのファイルに、全てのレイヤーが存在するわけではありません。

特定の名前がどれか一つでも引っかかったら削除したいのです。

 

これをもっと簡潔に書く方法はありますか?

 

This topic has been closed for replies.
Correct answer ajabon grinsmith

最適解はTen Aさんから出たと思うので、

こちらからは添削を…

削除系のスクリプトは配列・コレクションの後ろから処理するのがラクです。

仮に layers[1] が削除対象だったとして、

layers[j].remove(); のとき、後続のレイヤー群はインデックス順位が繰り上がります。

次に控えている layers[2] が、この瞬間 layers[1] になるわけです。

でも変数 j は j++ されてループを繰り返すため、

元 layers[2] だった現 layers[1] は処理を飛ばされ、元 layers[3] の現 layers[2] からの処理となりますね。

 

これを回避するためには、

layers[j--].remove();

または

for(j = layers.length - 1; j >= 0; j--){

と、降順ループに変更

などが考えられます。

余裕があったら自分のコードを直して再度チャレンジしてみてください。

2 replies

ajabon grinsmith
Community Expert
ajabon grinsmithCommunity ExpertCorrect answer
Community Expert
October 27, 2023

最適解はTen Aさんから出たと思うので、

こちらからは添削を…

削除系のスクリプトは配列・コレクションの後ろから処理するのがラクです。

仮に layers[1] が削除対象だったとして、

layers[j].remove(); のとき、後続のレイヤー群はインデックス順位が繰り上がります。

次に控えている layers[2] が、この瞬間 layers[1] になるわけです。

でも変数 j は j++ されてループを繰り返すため、

元 layers[2] だった現 layers[1] は処理を飛ばされ、元 layers[3] の現 layers[2] からの処理となりますね。

 

これを回避するためには、

layers[j--].remove();

または

for(j = layers.length - 1; j >= 0; j--){

と、降順ループに変更

などが考えられます。

余裕があったら自分のコードを直して再度チャレンジしてみてください。

nekkonekoAuthor
Inspiring
October 27, 2023

ありがとうございます。

 

ループするイコール

for(i=0; i<layers.length; i++)

これだ!って感じであまり何も考えずに書いていました・・・。

 

もしかしたら今まで作った削除系のものは書き直す必要があるかもです。

おかしいなと思ったことはあまりないのですが、削除系じゃないもので、一つ思い当たるものがあったので降順で試してみたいと思います!

 

わざわざありがとうございました。

ajabon grinsmith
Community Expert
Community Expert
October 27, 2023

(正解マークは複数の回答につけられますよー!)

Ten A
Community Expert
Community Expert
October 27, 2023

おそらくターゲットを配列に持った上でループするのが得策でしょう。

 

 

var targetLayers = ["レイヤー 4","レイヤー 5","レイヤー 6"];
for (var i=0;i<targetLayers.length;i++)
{
  try
  {
    app.activeDocument.layers.getByName(targetLayers[i]).remove();
  }
  catch(e){}
}

 

該当レイヤーがない場合はtry~catchでトラップすると良いです。

nekkonekoAuthor
Inspiring
October 27, 2023

ありがとうございます。

 

ターゲットの配列でループしたらよかったんですね。

レイヤーだからレイヤー配列でループしなきゃ!という謎の考えから離れられませんでした・・・。

 

教えていただいたようにやったらちゃんとできました。

ありがとうございました。

Ten A
Community Expert
Community Expert
October 27, 2023
ターゲットリストへのアクセスとレイヤーコレクションへのアクセスを比べると処理時の負荷は前者の方が軽くなります。コレクションを総当りで調べるか名前が合致するものをピックアップするかという選択になりますが、レイヤーコレクションの様に比較的物量が少ないものは差を感じにくいのですが、ループを行う際もajabonさんの指摘にもあるように削除時にコレクションの総数自体が変化するという事も考慮が必要になります。
レイヤーのように予めオブジェクトに一意に選択可能なnameプロパティのような物がある場合は有効に活用することを考えると良いでしょう。pathItemsのような場合でも予めnoteやnameプロパティを設定する事も可能ですから、そういったプロパティを設定する処理を予めワークフローに組み込んでおくと言うのも有効な手法です。