見出し画像

【photoshopJavaScript】レイヤーの順序を逆にする

結論

function reverse_layer_order(document){
   for(var index = 0; index < document.layers.length; index++){
       if(!document.layers[index]){continue}
       
       var key_layer = document.layers[0]
       var target_layer = document.layers[index]
       
       if(key_layer.name === target_layer.name){continue}
       if(target_layer.typename == "ArtLayer" && target_layer.isBackgroundLayer == true){continue}
       
       target_layer.move(key_layer, ElementPlacement.PLACEBEFORE)
   }
}

こう。「レイヤーを上から順番に最前面に出していけば、最終的に全部ひっくり返るよね」というやり方。

レイヤーの順序を移動するのは、こう。

target_layer.move(key_layer, ElementPlacement.PLACEBEFORE)

何がやりたいかっていうと

画像1

こうなっているレイヤー構成を

画像2

こうしたいんですね。

えっこれはレイヤーじゃなくてレイヤーセットだ? まあそうなんですけどやることは同じなんで勘弁してください。

やりたいのはフォルダの順序の変更なんですが、記事にするならフォルダの順序変えるよりレイヤーの順序変える方が汎用性高いかなって。

アクティブドキュメントを取得する

var document = app.activeDocument

アプリケーションオブジェクトからアクティブドキュメントを取得します。

アプリケーションオブジェクトはどこかで勝手に「app」という名前でインスタンスが作られていますので、いきなりapp.って書けばアクセスできます。と、言うことを毎回忘れて探します。いきなりapp.って書けばアクセスできます。

アクティブドキュメント内のレイヤー一覧を取得する

var layers = document.layers

でレイヤーの一覧が取れます。

ちなみに、Documentオブジェクトからレイヤーの一覧を取得出来るんですが、取得出来る「レイヤーの一覧っぽいもの」が何種類かあります。

document.artLayers……レイヤーフォルダを除いた、レイヤーのリストが取れる(調整レイヤーはリストに含まれる。ただし、レイヤーフォルダ内のレイヤーは調整レイヤーも含めてリストに含まれない)

document.layers……レイヤーフォルダを含む、全てのレイヤーのリストが取れる(※フォルダ内のレイヤーはLayerSetオブジェクトとして入ってくるので、フォルダ内のレイヤーに対しても全て処理をしたい場合工夫がいる)

document.layerSets……レイヤーフォルダだけのリストが取れる

document.layerComps……レイヤーカンプのリストが取れる。(レイヤーカンプがどんなものかについては調べてください)

用途に応じて取得しましょう。アートレイヤーだけ、とかレイヤーセットだけ、とかをごにょごにょしたいなら、layersで取得してから種類を判断するより、最初からartLayersで取得するのがよいでしょう。

どーーしても取得してから種類を判断して色々やりたいんだけど、という場合は、各要素のtypenameプロパティを取得してあげれば種類が判定できます。

今回はレイヤーセットだけ拾いたいので、サンプルコートでは

var layerSets = document.layerSets

を採用して進めています。

レイヤーリストをforで処理する

for(var index = 0; index < layerSets.length; index++){
       $.writeln(layerSets[index])
}

ついついfor...in使いたくなるんですが、for...in使うと、LayerSets(やLayers)が持ってるプロパティのキーまで拾ってしまって不都合なので、大人しく古式ゆかしい方法で回します。

レイヤーを並び替える

レイヤーの類いの並び替えにはmoveメソッドを使います。

target_layer.move(key_layer, ElementPlacement.PLACEBEFORE)

ArtLayer / LayerSet オブジェクトのいずれかに対して、moveメソッドを使います。

が、こいつ結構挙動に癖がありまして、「基準にするレイヤーと、その前に置くか後ろに置くかを指定すると、そのレイヤーの前/後に移動する」という、微妙に痒いところに手が届かない仕様です。直接「一番前!!!」とか「何番目!!!」とか指定できないのよ面倒ね。

と言うわけで、今回は「レイヤーの並び順を逆転させる」ということをやりたいので、「n番目のレイヤーを順番に、【今一番手前にあるレイヤー】の上に重ねる(=最前面に移動する)を繰り返す」という愚直な方法で行きたいと思います。

12345
と並んでいるレイヤーの、2枚目を最前面に移動すると
21345
続いて3枚目を最前面に移動して
32145
…………と繰り返して、最後まで移動すると54321に並び変わるというわけです。

順序指定のための定数について

moveメソッドを使ったレイヤー準入れ替えの際、移動先の指定にはScripting Constans=予め用意されている定数値を使います。

基準のレイヤーの上に重ねたい場合 ElementPlacement.PLACEBEFORE を、基準レイヤーの下に入れたい場合は ElementPlacement.PLACEAFTER を指定します。

ちなみに、ElementPlacementには他にもINSIDEとPLACEATBIGINNING、PLACEATENDというのもあるんですが、使える時と使えない時があります。

画像3

INSIDE、PLACEATBIGINNING、PLACEATENDは、「ArtLayerをLayerSet内に移動する」場合にしか使えません。移動させたい対象がレイヤーフォルダの場合はPLACEBEFOREとPLACEAFTERしか使えず、レイヤーフォルダをレイヤーフォルダの中に格納するということはできない模様。(レイヤーパネル上でマウスでドラッグすれば入るのにねー)

最前面のレイヤーを取得する

var key_layer = document.layerSets[0]

document.layerSetsの0番が最前面にあるレイヤーを指します。番号が大きくなるほど背面です。

forで回してn枚目のレイヤーを取得する

    for(var index = 0; index < document.layerSets.length; index++){
       var key_layer = document.layerSets[0]
       var target_layer = document.layerSets[index]
       target_layer.move(key_layer, ElementPlacement.PLACEBEFORE)
   }

layersやlayerSetsは先述のとおり、for…inで回すには不都合なので、古式ゆかしくindexを一つずつずらして処理します。

このとき、「最前面にあるレイヤー」はレイヤーを一枚移動させる度に変わるので、毎回取得しなおします。

エラー対策

エラーで落ちると悲しいので、紛れ込んでくる可能性の高そうなエラーは対策しておきます。

・layerSets[index]が存在しない(falseになる)場合処理を飛ばす
・レイヤーのtypenameがArtLayerで、かつisBackgroundLayerプロパティがtrueの場合、背景レイヤーなので重ね順の移動できなくてエラーになるので飛ばす
(・基準にするレイヤーと移動したいレイヤーの名前が同じ場合、移動する意味がないので飛ばしてもいい。飛ばさなくてもエラーにはならない)

ってことで、エラー対策を組み込んだ完成形がこちら。

function reverse_layer_order(document){
   for(var index = 0; index < document.layers.length; index++){
       if(!document.layers[index]){continue}
       
       var key_layer = document.layers[0]
       var target_layer = document.layers[index]
       
       if(key_layer.name === target_layer.name){continue}
       if(target_layer.typename == "ArtLayer" && target_layer.isBackgroundLayer == true){continue}
       
       target_layer.move(key_layer, ElementPlacement.PLACEBEFORE)
   }
}

↑すべてのレイヤーを取得する版

function reverse_layersets_order(document){
   for(var index = 0; index < document.layerSets.length; index++){
       if(!document.layerSets[index]){continue}
       if(document.layerSets[index].typename != "LayerSet"){continue}
       
       var key_layer = document.layerSets[0]
       var target_layer = document.layerSets[index]
       
       if(key_layer.name === target_layer.name){continue}
       
       target_layer.move(key_layer, ElementPlacement.PLACEBEFORE)
   }
}

↑レイヤーフォルダだけ取得する版

完成!!!お疲れ様でした。

この記事が気に入ったらサポートをしてみませんか?