Illustrator:文字の位置そのままで揃え方向を変えたい時に使うやつ

というわけでですね(何が)

しばらくスクリプトのことだらっだら書いてたんですけど、
今ウチの業務ってIllustratorばっかりなんですよな。。
InDesignほとんど出番ないんですよ。。
思い起こせば、Illustratorでドヤ顔できるスクリプトってまだ書いたことなくて。
あるかも知れないけどパッと思い出せないレベル。非公開配布したやつぐらいしか。

とりあえずで、自分にすぐ必要になったやつを書きました。
どんな物かって、むかしInDesign用に書いたやつの劣化移植版ですけども。
概要はリンク先から ↑ 基本機能の使い方を参照してくだされば。



ai_JustificationSwitcher.jsx

CS3以降ならなんでもてきとうに動くはず。

2016.11.01 ダイアログ出現座標を[450, 450]に指定。画面中央までマウス持っていくの大変だったので(自己都合)
2016.06.30 ボタンクリックが煩わしいので、使用頻度の高い「右 / 下揃え」をOKボタンに指定。つまり、リターンキーを叩くと「右 / 下揃え」が押されたことになります
2016.06.27 ドロップダウンリストが煩わしいので(スクリプトは書きやすかったのだが)ボタン操作に変更しました。また、アピャランスヘビーユーザのために単一オブジェクトからなるグループオブジェクトもサポートするよう改良しました。
2016.06.20 左揃えがうまくいっていない件、回避案をコメントいただき反映しました。再度ダウンロードいただき上書きお願いします。
すーませんすーません。
2016.06.17 CS4以降で「左/上揃え」がうまくいかないようです。古くからあるバグみたい…
回避策が出るまで不便なままお待ちください。すーみません。


あそびかた

こういう、かわいいデータがあります。
このままだと、とても直しにくい。

160520a

いい感じにしたいテキストをまとめて選択します。
テキスト以外も選択しちゃっていいです(グループの場合、その内容までは掘り下げてないので白矢印とかでどうぞ)。
そんでスクリプト実行。

160520f
なんか出ます。

リストから目的の揃え方向を選択してプリーズボタンをカチ。
プリーズボタンって久々に出たなあw

160520c

やったー。
という内容。

コードはこちら

ついでにフローチャートも。
原型がコレ

160520d

それをループにして、
ついでにパレットとかつけました。
ってInDesign版のコピペ流用だけど。

160520e

どやっ(自己満足)

ちなみに今回(も)「おーけー流星号」の呪文を唱えました。。
プロパティさえわかればあとはカンタンなんですよ。
(と言いつつ他の箇所を2回書き間違えたんですが)
(しかもフタ開けてみたら当てズッポでも正解しそうな浅い所の簡単なプロパティだったんですが)
(忙しかったんですもの)
コードのやり取りにGitHubを使ってみたんですが、あのーグダグダでしたw

でーす。

タイトル考えてなかったけどInDesignでスクリプト覚えましょうそうしましょう(月)

はいはいどもども。続いてないけど続き。

前回はスクリプトで処理するってどういうこと、
プロパティ探せ、オーケー流星号
という内容でした。
部品だけ並べたてたかんじ。これだけではまだ敷居が高いと思わせてしまうでしょう。

今回は実際に白紙状態から組み立ててってみます。
実用的なヤツがいいよなあ。
でも長らく実務から離れてるんだよな。


んでは、

空の図形を削除するスクリプト

を作ってみるとします。一見かんたんっぽいし。

まずは脳内または紙面または画面上に、フローチャートを作成してみましょう。(実際あまりやったことありませんが…)
プログラマー的な書式がベストでしょうけど(ぐぐりましょう)、自分がわかれば(数日後の自分がわかれば)どんな書き方でもいいでしょう。

ここで、いま思い付く限りの可能性を書き出して対処していきます。
ウチはまるっきりの初心者ではないのでここでほぼばっちりめに書けてしまいますが、それだとちょっとあれなので、わざと過去の経験を生かし、見落としまみれの穴だらけにしてあります。
160512a

せめてもうちょっとまじめに書きましょうか。
あと、フリーフォントは字間がイラッとする事が多いので気をつけましょう(使わせてもらっといてなんなんですけど…)


というわけでまだまだ大ザッパだけど、こんなかんじ。
160512b

これを眺めた時点で、処理の流れが間違ってないか確認。
これだとうまく動かない要素が思い付く場合もありますが、実際にスクリプトを動かしてみてから吠え面かくのもアリでしょう。
ではこれを設計図として、実際にスクリプトを書いてみましょう。
※今回は不完全なソースコードがとっちらかるので、いつものkamisetoさんの置き場は使いません。

さて。いいのかこれで。ほんとにいいのか。


まず処理対象はドキュメント内すべてのページアイテムにしました(つもり)。
allPageItemsは前回まで扱ってきたコレクションオブジェクトと違い、ほぼ純粋に配列です。ただし読み取り専用です。ここから直接足したり引いたり書き換えたりはできません。これをループ処理。
allPageItemsのi番目の塗りカラー(fillColor)と線カラー(strokeColor)それぞれのnameプロパティを参照しています。
fillColorとsrtokeColorはどちらもSwatchクラスです。まーそのスウォッチ。これの名前が[なし]に一致しているかを見ているわけです。

注意点は、ベーシックなスウォッチ以外ではこの方法は万能ではないこと。ベーシックな物でも黒、白などはカラー値だけが一致していてスウォッチが適用されていない場合があるわけで。。
そんなこんなーで、塗り線とも[なし]なら、ブリッと削除。allPageItemsは読み取り専用ですが、要素のPageItemオブジェクトは削除とかできます。するとallPageItemsのlengthは1つ減ります。そして次のオブジェクトを、と順々処理。全部やったら挨拶して終了。
という内容ですが。
まあ、ザルですw 穴だらけ。


とりゃえず一番の問題点は、えー、前々回の図を参照。
160427d

ループ中、i = 0 のとき、アカレンジャーを削除すると残った人たちが一歩ずつ前に詰めます。
でも変数iはそんな事情なんか知りません。教えてないので。無邪気なままです。ループは淡々と繰り返され、今度は i = 1 で処理されます。
すると、アカの次にいたアオがスルーされてキレンジャーが次回の処理対象になってしまう。あらあら大変。
解決法はいくつか。


・allPageItemsをいちいち取得し直しているので、前もって代入しておいた配列変数をループ処理する
・allPageItemsを逆順(昇順 -> 降順)で処理する
・オブジェクトを削除した直後に変数iを -1 しておく
・すぐ削除せず、「あとで消す」と記憶だけしておいて、チェックのループが終わったら最後にまとめて削除する


4通りとも書いてみせるのもかさばるし紛らわしいので。1つめ+4つめの案だけ採用して書き直してみましょう。
※諸事情でそうなりましたが、実際のところ1つめ or 4つめ、どちらかだけの実装で直りますこれ。

しつこいけどフローチャートから直しておきますね。
がんばってかきました。
160512c

これをもとにスクリプトを書き直します。最後の挨拶は完全にネタなので気軽に消しました。

今度はどーでしょう。


「最後にまとめて削除する」と書きましたが、結局はまたループで、1個ずつ削除するわけですが…
削除を実行している行は、
hoge = kesuAry.shift( );
hoge.remove( );
を1行で済ませたもの、と考えてください。


これで「塗りも線も[なし]のオブジェクト」は残らず削除される事でしょう。
どうじゃ、ずんとましになったじゃろう。
これ、非表示レイヤーの中身も関係なく削除されるんですよー。すごいでしょー。
でも、レイヤーやオブジェクトそのものにロックがかかっていると削除できません。内包しているグループも同様です。


要件のアラ探しは尽きないんですが、望まぬ処理をしてくれようとしてエラーで止まるヤツは、自分使い用であれば無視してもいいかと思います。
もっとも、処理途中で止まるやつは取り消しも大変で厄介なこともあるんですが。。

さておき、ここでまた問題ですね、はい。


・非表示オブジェクトは許してあげたい(とした場合)
・ロックがかかってたら解除してから削除しないといけない
・でもレイヤーのロックは一時的に解除しても最後には元通りにしてあげたい(とした場合)


……とかですね。あのー今回はやりませんけども。特にロックはものすごくめんどくさい事になるのでやりません。今回は。

とりあえずこのへんで終わりにしたいんですけど、
気付かないフリをして進めた様々な問題を、脳内で思い付く限り晒して締めます。


・塗り&線カラーがあっても不透明度が0%だった場合は?
・回り込みオブジェクトだった場合は?
・テキストフレームだった場合は?
・画像が配置されたグラフィックフレームだった場合は?
・マスターページアイテムだったら?
・見えないボタンだったら?
・インラインオブジェクトは消せなくない?


……ぐらいですね。まだまだ出そうですけど。

以上、おそまつさまでした。
ちゃんとした人にはソースコード配置のため今回から使い出したGitHubが全然使いこなせてないのがマルバレでほんとお恥ずかしい限りですけども。
ちょっとこっち方面を覚えていかなければいけなくなってきているのでがんばります。

でーすー。

タイトル考えてなかったけどInDesignでスクリプト覚えましょうそうしましょう(日)

どもども。ども。

前回の反響、ひとことで言うと「おー、やったー! なんかわかりそうな気がする(けどわからん)!」
手前勝手に書き殴ったスクリプトを一行ずつ解説しても、全体がなんでそんなカタチなのかを省いているため、あんまりお役に立ててなかったかもっぽいですなあ。
「スクリプト拾ってきたぜ、ちょっといじりたいぜ、でも何が書かれてるのかサッパリなんだぜ」
というときの読み解きのヒントになれば、とも思ったのですが。
手作業的思考とスクリプト的思考の垣根をとっぱらうのを先にやるべきなのでしょう。

奇しくも前回の次にやろうとした「縦組みにも対応させよう」は、実はもともと対応できちゃっててコケたため、
また、「回転のかかったテキストフレームへの対応」はあまりにもニッチすぎる上、ふつうに書ける人向けになってしまうので、今回はその「手作業ではこうだけどスクリプトではどうなの」をやります。resolve( )の出番は今度だ。。


今回もInDesignをダシに進めていきます。
例はCS6でやりますが、CS4以降ならなんでもいいです。CS3以前は今回ごめんなさい。

まず、InDesignを起動します。
対応バージョンのExtendScriptToolKit(以下ESTK)を起動します。
ESTKで「新規Javascript」を開きます。
新規書類「ソース1」が出ました。やったー。
160502a

今回はInDesign用のスクリプトを書くので、左上の対象アプリケーションをInDesignにします。
これで、ESTK上からスクリプトを実行するとInDesignを対象とすることができます。
冒頭の行に
#target indesign
と書いて実行してもも同様の結果なんですけど、まあ地味に基本からということで。。

また、右上のメニューから当該バージョンのInDesignを選択しておくと、オブジェクト名の入力補助が行われます。これ、挙動の遅さに我慢できない人もいると思うので、まあ任意で。
160502b

ではこの中にスクリプトを書いていきます。


まずは以下の一行だけ。書いたらすぐ実行してみましょう。
app.documents.add( );
実行すると新規ドキュメントが開かれます。
前回っぽく言うと、InDesignのドキュメントコレクションに要素を1つ追加しています。

理解を深めるため、確認を兼ねてちょっと書き足します。
開かれているInDesign上の新規ドキュメントは閉じちゃっていいですが、どっちでもいいです。


function pepsi ( ) {
alert (app.documents.length);
}

pepsi ( );
app.documents.add ( );
pepsi ( );


はいいきなり出しましたけど関数。Documentsのアイテム数をアラートで参照するという内容。
別々のところで計2回やる処理なので、わざとらしく関数化してみました。
pepsi( )と書いた行でalert(app.documents.length); が実行されます。
ドキュメントを追加、その前後でドキュメントの個数を確認、という内容です。


次に、新規ドキュメントの中に、なんとなく長方形を作ってみましょう。
開かれているInDesign上の新規ドキュメントは閉じちゃっていいですが、どっちでもいいです。

app.documents.add( );
app.documents[0].rectangles.add( );

一行目は最初に書いた物と同じ、新規ドキュメントを開きます。
二行目で、Documentsコレクションの0番目のアイテム(最前面ドキュメント)に長方形追加しています。
Rectangleは長方形オブジェクト。正方形でも長方形オブジェクトとなります。
この長方形は今のところ「長方形こしらえます」しか書いていないので、位置やサイズはてきとうになりますが、今回はそこまでやりません。
この長方形ができたドキュメント、次でも使うのでそのままにしといてください。


次、この長方形を削除してみましょう。
の前に、手作業だとどういう手段になるでしょうか。
・選択してdeleteキー
・選択してメニュー 編集>消去
とかでしょうか。なんにせよ選択は必須ですか。

スクリプトではこうなりますか。
ドキュメント0個目の、長方形0個目を、削除するスクリプト
app.documents[0].rectangles[0].remove( );
このように、ひとつのオブジェクトを処理するために、そのオブジェクトが何の中の、そのまた何の中にあるのか、を書かなければいけません。
めんどくさいでしょうか。まどろっこしいでしょうか。でも選択してなくても削除できるんですよこれ。わーすごーい。


もうひとつ。今度はあらかじめ手作業で、前面ドキュメント上に楕円形を1個作成しといてください。
まんまるじゃない方がいいです。
160502c

では、これを20°回転する、1行のスクリプトを書いてみましょう。
app.activeDocument.ovals[0].rotationAngle = app.activeDocument.ovals[0].rotationAngle + 20;

app.activeDocumentは、ドキュメントが何個あっても関係なく、最前面ドキュメントの事。
app.documents[0]と大差ないんですが、2個以上のドキュメントをとっかえひっかえ処理する場合以外はもうコレの方が間違いないかと。
Ovalは楕円形。まんまるでも楕円形オブジェクトとなります。
rotationAngle は、図形オブジェクトクラスが持っている回転角の値。これをプロパティといいます。用語の使用は極力避けて進めてますが、これは覚えましょう。「お前の回転角は、お前の回転角+20だわよ」と書いたわけです。決して「お前、20°回転しろ」ではないので注意。プロパティはオブジェクトの状態を表す物、という覚え方でいいんでないかなあ。命令というよりは指定、というか。ふんわり進行ですけども。
160502d

このスクリプトは、こう書くこともできます。同じ意味となります。
app.activeDocument.ovals[0].rotationAngle += 20;
この「+=」の仲間については「代入演算子」で調べるとよいです。


仮にこの楕円形を何度も何度も処理する場合、いちいち
app.activeDocument.ovals[0].rotationAngle
と書くと、書く方も読む方も疲れるので(実行する方は疲れませんが)、変数に入れてしまうとよいです。
var obj = app.activeDocument.ovals[0];
obj.rotationAngle += 20;
これで変数objを楕円形オブジェクトとして扱うことができます。

ただし、こう書くと具合が違います。
var obj = app.activeDocument.ovals[0].rotationAngle;
obj += 20;
この場合、変数objには楕円形の回転角のがなんでもないひとつの数値として代入されるだけで、いくらobjの値を変えても楕円形はビクともしません
プロパティには書き換え可能な物と読み取り専用の物があります。どれがどれなのかはオブジェクトモデルビューア(後述)を参照します。


次。引き続き、楕円形のあるドキュメントを流用します。
前面ドキュメントの0個目の楕円形をX方向に10、Y方向に20の位置に複製するスクリプト
var obj = app.activeDocument.ovals[0];
obj.duplicate (“”, [1020] );
書いたら何度か繰り返し実行してみましょう。

前述のプロパティが「お前の◯◯は◯◯だ」的な内容だったのに対し、こちらは「お前、◯◯しろ」となります。メソッド(関数)といいます。
複製されたオブジェクトは元オブジェクトの前面に作成されるので、次回実行時はその複製された楕円形が0個目として処理対象となり、結果、実行するたびずんずん右下に複製されていきます。
160502e

プロパティが状態を表す物なら、メソッドは命令そのものです。おけつに( )が必ずつきます。( )内に「どのぐらい」、「何を」といった引数が必要な物と不要な物があります。


対象オブジェクトのプロパティを見たり書き換えたり、メソッドを実行したりすることが「スクリプトで処理する」ということです。突き詰めればこれだけなのですわ。。
ある程度構文が書けるようになると、今度はその当該プロパティ探しで苦戦する事となります。間違いない。
twitter上で「おーけー流星号、◯◯のプロパティ教えて」と書くと30秒ほどで教えてもらえるという都市伝説があります。


プロパティ(メソッド)のさがしかた(日)

ESTKのヘルプメニューから「オブジェクトモデルビューア」を開きます。
過去に小さな勉強会で配布した資料よりスクショ引用。
160502f

でアプリケーションを選択すると、にそのアプリケーションで使えるクラス(オブジェクト)がだーっと出ます。そこから1つ選ぶと、
次は、まあおいといて(てきとうてきとう)
で選んだクラスが持つプロパティ、メソッドなどがだーっと出ます。そこから1つ選ぶと
にその説明やデータ型などが英語で出る、という仕組みです。英語だいすき(白目)
青の「=X」アイコンがプロパティ、赤の「{}」アイコンがメソッドです。
には、プロパティは「名前:データ型」、メソッドは「名前:返り値のデータ型」として書かれています。
任意のテキストフレームからストーリーをいじりたいと思ったら、textFrame.parentStoryと書くと辿りつけるわけです。
それでまたからStoryクラスを選んで…という。七面鳥くさいですか。ですね。


プロパティ(メソッド)のさがしかた(月)

スクリプトを書きます。プロパティを見たいオブジェクトをてきとうに変数に入れておきます。
長方形かなんか、てきとうに選択しといてください。
var a = app.selection[0];
alert(“うんこうんこうんこ”);
この2行ぶんを書いたら、2行目の行番号の脇の空いたところをカチします。赤丸がつきます。
これをブレークポイントといいます。赤丸がある行を実行する直前でスクリプトは一時停止されます。
あとで用済みになった赤丸はカチカチすると消えます。茶丸もあるんですが今回は割愛。
赤丸をつけるかわりに
$.bp( );
と書いても一時停止できるんですけど、これも今回は割愛。
160502g

行が黄色くなったらそこで一時停止中です。ここでウィンドウメニューからデータブラウザを出してみましょう。
変数aが上の方にいます。aのオブジェクトクラス名が見えますね。
これの▶︎を展開すると、aの持つプロパティやメソッドがだーっと見れます。
160502h

この中でどれかプロパティを選択すると、データブラウザの一番上にある欄に値が出ます。ここで値を書き換えるとじかにそのプロパティの値を変更できるのですが、近年バージョン(特にIllustrator)はレスポンスがイマイチ不安なので覚えなくていいです。
その代わりに、ウィンドウメニューからJavaScriptコンソールを出します。ここに式を書いてreturnすると結果が出ます。
1 + 1 と書いてreturnバシすると「結果:2」が返ります。もう電卓いらない!
長方形を選択している状態で、
a.rotationAngle と打ち込んでreturnしてみると、長方形の回転角が結果として出ます。
↑この行にまたカーソルを送り、後ろに続けて
+= 20 と打ち込んでreturnしてみると、長方形が+20°回転します。ドキュメント上ですぐには反映しないかも。
160502i「ソース1」ウィンドウの実行ボタン(再生ボタンっぽいやつ)を押すと処理は続行され、スクリプトは終了します。
停止ボタンはその時点で処理を中断終了します。
終了後、ドキュメント上ではオブジェクトが回転されているかと思います。


プロパティにはそれぞれ固有のデータ型があります。上で紹介した2通りのどちらでも確認することができます。
たいがいは数値(整数限定の場合あり)や文字列ですが、固有オブジェクトの場合もあります。
長方形の属性を見てみましょう。オブジェクトメニュー>オブジェクトの属性 で見れるやつです。
JavaScriptコンソールに以下を入力して実行
a.contentType
ウチは空のグラフィックフレームを作ったので、結果はGRAPHIC_TYPE と出ました。
バージョンによっては、よくわからん10ケタの数字が出るかもしれません。が今回は割愛。
160502j
試しにこれをテキストフレームに変換してみましょう。
オブジェクトモデルビューアでRectangleクラスを選択、contentTypeプロパティを見ると、contentTypeプロパティのデータ型はContentTypeクラスだぜ、と表示されております。
160502k

右ペインの青文字になったContentTypeをカチすると、ContentTypeクラスのオブジェクトモデルを見ることができます。
するとプロパティが3種。グラフィックフレーム、テキストフレーム、割り当てなし。 ソース1を終了して、以下を書き足します。
a.contentType = ContentType.TEXT_TYPE;
ここ、a.contentType = TEXT_TYPE; とはならないので注意。とりゃえず、「だってそうなんだもん」として覚えておきましょう。
実行すると長方形はテキストフレームに変わります。スクショありません。



まとめ(無理矢理)
・したい処理の対象になるプロパティ、メソッドを探す
・見つけたらデータ型を確認する
・データ型を確認したらプロパティの値を書き換える

ここまでざっくりでも理解できたら、あとはやる気だけっすわ。ほんとに。
次回、実際にスクリプトをゼロから書くぜって時のウチなりの組み立て方などを。

でーす。