Kの小技-06 Illustrator スクリプト 条件式を入力して任意の位置にオブジェクトを複製 – 後編1

記事作成時yamakei作業環境(2018/5/18)
OS : macOS sierra (10.12.4),
Adobe Illustrator CC 2018 (22.1),
Adobe Extendscript Toolkit CC (4.0.0.1 Extendscript 4.5.5 ScriptUI 6.2.2)

yamakeiが普段の作業の中で覚えた技や便利機能を主観多めでご紹介。

第6回は第5回に引き続き「選択したオブジェクトを入力した条件式の座標に複製するスクリプト」を組んでいきたいと思います。
え?前回から5ヶ月も経っているって?ハハそんな馬鹿n(更新サボって申し訳ありませんでしたー!!)

前回は選択中オブジェクトの取得と位置座標の取得を解説いたしました。
しかし、いざ残りの部分をコーディング・解説して行こうとすると作業量が予想以上にしんどいものになってしましました。何とか希望通りのスクリプトは組むことができたので、今回はスクリプトのフローチャートとコード、そして実際にスクリプトを使用した例を何点か掲載するにとどめてお茶を濁させていただきたいと思います。
細かい解説は次回以降の更新にて。

■ フローチャート


■ スクリプト

//------------条件式入力ダイアログ用変数の初期化------------------------
var win_width = 400;  //ウインドウの幅を指定
var win_hight = 360;  //ウインドウの高さを指定
var dlWin;  //ダイアログウインドウを格納する変数
var btnOK;  //OKボタンを格納する変数
var btnCancel;  //キャンセルボタンを格納する変数

//------------条件式用変数の初期化------------------------
var condition_n;  //複製する個数の条件式(文字列)を格納する変数
var condition_x;  //複製後の中心X座標の条件式(文字列)を格納する変数
var condition_y;  //複製後の中心Y座標の条件式(文字列)を格納する変数
var condition_scale;  //複製後の倍率の条件式(文字列)を格納する変数
var condition_rotate;  //複製後の回転角度の条件式(文字列)を格納する変数

var n;  //個数の条件式(文字列)を計算後の数値を格納する変数
var x;  //中心X座標の条件式(文字列)を計算後の数値を格納する変数
var y;  //中心Y座標の条件式(文字列)を計算後の数値を格納する変数
var scale;  //中心Y座標の条件式(文字列)を計算後の数値を格納する変数
var rotate;  //回転角度の条件式(文字列)を計算後の数値を格納する変数

//------------オブジェクト用変数の初期化------------------------
var acDoc = app.activeDocument;  //現在のドキュメントを変数acDocに格納
var SelectObject = [];   //選択中オブジェクトを格納する配列

var baseObject = [];  //複製の起点となるオブジェクトを格納する配列
var duplicateObject = [];  //複製したオブジェクトを格納する配列

try {
  //------------イラレ上で選択中のオブジェクトを格納------------------------
  for (var i=0; i < acDoc.selection.length; i++) {
    SelectObject.push(acDoc.selection[i]);
  }

  //------------イラレ上で何も選択されてない場合のエラー処理------------------------
  if (SelectObject.length < 1) {  //選択中オブジェクトの要素数が1より少ない(何も選択されていない)場合
    throw "複製するオブジェクトを選択してください。";  //エラーを投げて処理終了
  }

  //------------条件式入力ダイアログを作成------------------------
  dlWin = new Window("dialog","複製の条件式入力",[0,0,win_width,win_hight]);   
  dlWin.center();  //ウインドウ表示位置をモニターの中心に移動

  dlWin.add ("statictext", [10,10,60,40], "個数n=");  //ウインドウに固定文字を追加
  condition_n = dlWin.add("edittext",[60,10,win_width-10,40],1);  //個数nの入力テキストボックスを追加、初期値は1に設定

  dlWin.add ("statictext", [10,50,160,80], "i番目の図形の中心座標");  //ウインドウに固定文字を追加
  dlWin.add ("statictext", [10,80,60,110], "x座標=");  //ウインドウに固定文字を追加
  condition_x = dlWin.add("edittext",[60,80,win_width-10,110],0);  //図形の中心x座標条件式の入力テキストボックスを追加
  dlWin.add ("statictext", [10,110,60,140], "y座標=");  //ウインドウに固定文字を追加
  condition_y = dlWin.add("edittext",[60,110,win_width-10,140],0);  //図形の中心y座標条件式の入力テキストボックスを追加

  dlWin.add ("statictext", [10,150,win_width-10,180], "i番目の図形の倍率(オリジナルサイズの何倍か)");  //ウインドウに固定文字を追加
  dlWin.add ("statictext", [10,180,60,210], "倍率=");  //ウインドウに固定文字を追加
  condition_scale = dlWin.add("edittext",[60,180,win_width-10,210],1);  //図形の倍率条件式の入力テキストボックスを追加、初期値は1に設定
  dlWin.add ("statictext", [10,210,win_width-10,240], "i番目の図形の回転角度(度数入力)");  //ウインドウに固定文字を追加
  dlWin.add ("statictext", [10,240,60,270], "度数=");  //ウインドウに固定文字を追加
  condition_rotate = dlWin.add("edittext",[60,240,win_width-10,270],0);  //図形の回転角度条件式の入力テキストボックスを追加、初期値は0に設定

  btnOK = dlWin.add("button",[10,300,130,330],"OK",{name:"ok"});  //ウインドウにOKボタンを追加
  btnCancel = dlWin.add("button",[140,300,260,330],"cancel",{name:"cancel"});  //ウインドウにCANCELボタンを追加
  btnCancel.onClick = function(){dlWin.close(); throw "end";}

  dlWin.show();  //作成したウインドウを表示


  //------------複製の起点となるオブジェクトの準備------------------------

  //複製するオブジェクトが単体の場合、そのまま複製して変数baseObjectに格納
  if(SelectObject.length == 1) {  //選択中オブジェクトの要素数が1(単体)の場合
    baseObject = SelectObject[0].duplicate();  //選択中オブジェクトを複製して変数baseObjectに格納
    SelectObject[0].selected = false;  //複製元SelectObject[0]の選択状態を解除する
  }

  if (SelectObject.length > 1) {  //選択中オブジェクトの要素数が1より多い(複数)場合
    var newGroup = acDoc.groupItems.add();  //現在のドキュメントに空のグループ変数newGroupを追加
    newGroup.move(acDoc, ElementPlacement.PLACEATBEGINNING);  //空のグループ変数newGroupを現在のドキュメントの先頭レイヤーに移動
    for (var i = 0; i < SelectObject.length; i++) {
      SelectObject[i].duplicate(newGroup, ElementPlacement.PLACEATEND);  //変数SelectObject内のi番目要素をグループ変数newGroup内の末尾レイヤーに複製して格納
      SelectObject[i].selected = false;  //複製元SelectObject[i]の選択状態を解除する
    }
    baseObject = newGroup;  //グループ化したオブジェクトを変数baseObjectに格納
  }

  //起点オブジェクト(baseObject)の中心をイラレのワークスペース原点に移動
  var boGb = baseObject.geometricBounds;  //起点オブジェクトの上下左右座標を習得
  var boCenterX = (boGb[0] + boGb[2]) / 2;  //起点オブジェクトの中心X座標を取得
  var boCenterY = (boGb[1] + boGb[3]) / 2;  //起点オブジェクトの中心Y座標を取得
  baseObject.translate(-boCenterX, -boCenterY);  //起点オブジェクトの中心座標が原点(0,0)となるように移動


  //------------オブジェクトの複製処理------------------------
  n = parseInt(condition_n.text, 10);  //ダイアログで入力した個数nの数式を整数に変換

  //複製オブジェクトの計算・作成・加工
  for (var i = 1; i <= n; i++) {  //iの初期値1、条件式入力の開始番号に揃える

    //i個目の複製オブジェクトに関する計算
    //$.writeln("i : " + typeEquals(i) + ","+ i );  //デバッグ用、Toolkitコンソールにiの型と値を表示
    //$.writeln("n : " + typeEquals(n) + ","+ n );  //デバッグ用、Toolkitコンソールにnの型と値を表示

    x = eval(condition_x.text);  //i個目の複製オブジェクトの中心X座標計算
    //$.writeln("x : " + typeEquals(x) + ","+ x );  //デバッグ用、Toolkitコンソールにxの型と値を表示

    y = eval(condition_y.text);  //i個目の複製オブジェクトの中心Y座標計算
    //$.writeln("y : " + typeEquals(y) + ","+ y );  //デバッグ用、Toolkitコンソールにyの型と値を表示

    scale = 100 * eval(condition_scale.text);  //i個目の複製オブジェクトの倍率計算
    //$.writeln("scale : " + typeEquals(scale) + ","+ scale );  //デバッグ用、Toolkitコンソールにscaleの型と値を表示

    rotate = eval(condition_rotate.text);  //i個目の複製オブジェクトの回転角度計算
    //$.writeln("rotate : " + typeEquals(rotate) + ","+ rotate );  //デバッグ用、Toolkitコンソールにrotateの型と値を表示

    //i個目の複製オブジェクトの作成・加工
    duplicateObject = baseObject.duplicate();  //起点オブジェクトを複製して変数duplicateObjectに格納
    duplicateObject.translate(x, -y);  //複製オブジェクトを移動
    duplicateObject.resize(scale, scale);  //複製オブジェクトを拡大
    duplicateObject.rotate(rotate);  //複製オブジェクトを回転
  }
  $.writeln("end"+ "\n");  //デバッグ用、Toolkitコンソールに「end」と表示

  baseObject.remove();  //不要となった起点オブジェクトを削除

  //------------条件式確認アラート------------------------
  alert (
    "条件式\ni番目が\n" + 
    "x = " + condition_x.text + "\n" + 
    "y = " + condition_y.text + "\n" + 
    "大きさが" + condition_scale.text + "倍\n" + 
    "反時計回りに" + condition_rotate.text + "度回転\n" + 
    "全部で" + parseInt(condition_n.text, 10) + "個複製", "");

} catch(error) {
  if (error != "end") {
    alert (error);
  }
}

//デバッグ用関数
function typeEquals(obj) {
  var typekind = ["String", "Number", "Boolean", "Date", "Null", "Array", "Object", "Error", "RegExp", "Undefined"];
  var clas = Object.prototype.toString.call(obj).slice(8, -1);
  for (var i=0; i < typekind.length; i++) {
    if (clas === typekind[i]) {
      return clas;
    }
  }
}

うん、長いですね。

■ スクリプト実行結果

▼条件式入力ダイアログ

▼複製元オブジェクト-楕円

▼複製条件式-楕円

▼条件式確認アラート-楕円

▼複製結果-楕円

▼複製元オブジェクト-三日月

▼複製条件式-三日月

▼複製結果-三日月

▼複製元オブジェクト-3つのオブジェクト(透過5%)

▼複製条件式-3つのオブジェクト(透過5%)

▼複製結果-3つのオブジェクト(透過5%)

ひとまず今回はこんなところで。