金曜日, 10月 09, 2026

JavaScriptでAI遊び 108 
オブジェクトを設定した直径の円に対して指定数を均等配置

選択したオブジェクトを設定した直径の円に対して指定数を均等配置します。

#target illustrator

(function () {

if (app.documents.length === 0) {
alert("ドキュメントを開いてください。");
return;
}

var doc = app.activeDocument;

if (doc.selection.length !== 1) {
alert("配置する元のオブジェクトを1つ選択してください。");
return;
}

var source = doc.selection[0];

// =========================
// ダイアログ
// =========================

var dialog = new Window("dialog", "円周上に均等配置");

dialog.orientation = "column";
dialog.alignChildren = "left";

// 配置数
var countGroup = dialog.add("group");
countGroup.add("statictext", undefined, "配置数:");

var countInput = countGroup.add("edittext", undefined, "12");
countInput.characters = 8;

// 円の直径
var diameterGroup = dialog.add("group");
diameterGroup.add("statictext", undefined, "円の直径(mm):");

var diameterInput = diameterGroup.add("edittext", undefined, "100");
diameterInput.characters = 8;

// 開始角度
var angleGroup = dialog.add("group");
angleGroup.add("statictext", undefined, "開始角度(°):");

var angleInput = angleGroup.add("edittext", undefined, "0");
angleInput.characters = 8;

// ボタン
var buttonGroup = dialog.add("group");
buttonGroup.alignment = "right";

var cancelButton = buttonGroup.add("button", undefined, "キャンセル");
var okButton = buttonGroup.add("button", undefined, "配置");

cancelButton.onClick = function () {
dialog.close(0);
};

okButton.onClick = function () {
dialog.close(1);
};

dialog.defaultElement = okButton;
dialog.cancelElement = cancelButton;

if (dialog.show() !== 1) {
return;
}

// =========================
// 入力値
// =========================

var count = parseInt(countInput.text, 10);
var diameterMM = parseFloat(diameterInput.text);
var startAngle = parseFloat(angleInput.text);

if (isNaN(count) || count < 1) {
alert("配置数は1以上の整数を入力してください。");
return;
}

if (isNaN(diameterMM) || diameterMM <= 0) {
alert("直径は0より大きい数値を入力してください。");
return;
}

if (isNaN(startAngle)) {
startAngle = 0;
}

// =========================
// mm → pt
// =========================

function mmToPt(mm) {
return mm * 72 / 25.4;
}

var diameter = mmToPt(diameterMM);
var radius = diameter / 2;

// =========================
// 元オブジェクトの中心
// =========================

var bounds = source.visibleBounds;

var centerX = (bounds[0] + bounds[2]) / 2;
var centerY = (bounds[1] + bounds[3]) / 2;

// =========================
// ガイドとなる円を作成
// =========================

var circle = doc.pathItems.ellipse(
centerY + radius,
centerX - radius,
diameter,
diameter
);

// 塗りなし
circle.filled = false;

// 線あり
circle.stroked = true;

// 線幅 1pt
circle.strokeWidth = 1;

// 黒線
var black = new RGBColor();
black.red = 0;
black.green = 0;
black.blue = 0;

circle.strokeColor = black;

// 円を最背面へ
circle.zOrder(ZOrderMethod.SENDTOBACK);

// =========================
// 円周上に均等配置
// =========================

for (var i = 0; i < count; i++) {

var angle =
(startAngle + (360 / count) * i)
* Math.PI / 180;

var x = centerX + radius * Math.cos(angle);
var y = centerY + radius * Math.sin(angle);

var obj;

if (i === 0) {
obj = source;
} else {
obj = source.duplicate();
}

// オブジェクト中心
var b = obj.visibleBounds;

var objCenterX = (b[0] + b[2]) / 2;
var objCenterY = (b[1] + b[3]) / 2;

// 指定位置へ移動
obj.translate(
x - objCenterX,
y - objCenterY
);
}

})();

オブジェクトを選択して実行し・・・

デフォルト値を無修正のまま[配置]をクリックすれば・・・

円に均等配置されます。

もしろんグループ化されているオブジェクトも有効です。

配置数を変更すれば・・・

こんな感じです。