ラベル JavaScript の投稿を表示しています。 すべての投稿を表示
ラベル JavaScript の投稿を表示しています。 すべての投稿を表示

金曜日, 9月 12, 2025

JavaScriptでAI遊び 67 
Illustratorでスピログラフを描画


Illustratorでスピログラフを描画させてみました。

■スピログラフのパラメータ
外側の固定円(半径 R)
内側の回転円(半径 r)
描画点の距離 d(内円の中心からの距離)
ステップ数 s(1ユニットのパス数)
角度 θ(回転角)

■スピログラフの方程式
スピログラフの曲線 (x, y) は、以下のパラメータ方程式で表されます。

基本形(ハイポサイクロイド)
x(θ)=(R-r)cos(θ)+d cos(((R-r)r)θ)
y(θ)=(R-r)sin(θ)-d sin(((R-r)r)θ)

ここで:

θ は回転角(0 から 2π × ループ回数 まで変化)
(R - r) の比が整数であれば閉じた軌跡になる

#target illustrator
function drawSpirograph(doc, centerX, centerY, R, r, d,
        steps, rotations) {
var path = doc.pathItems.add();
path.stroked = true;
path.filled = false;
path.strokeWidth = 1;
var points = [];
for (var i = 0; i <= steps * rotations; i++) {
var theta = (Math.PI * 2 * i) / steps;
var x = (R - r) * Math.cos(theta) +
            d * Math.cos(((R - r) / r) * theta);
var y = (R - r) * Math.sin(theta) -
            d * Math.sin(((R - r) / r) * theta);
points.push([centerX + x, centerY + y]);
}
var pathPoints = path.pathPoints;
for (var j = 0; j < points.length; j++) {
var p = pathPoints.add();
p.anchor = points[j];
p.leftDirection = p.anchor;
p.rightDirection = p.anchor;
}
}

// ユーザー入力ダイアログを表示
function getUserInput() {
var dialog = new Window("dialog", "スピログラフ設定");
dialog.add("statictext", undefined, "外円の半径 (R):");
var RInput = dialog.add("edittext", undefined, "150");
RInput.characters = 5;
dialog.add("statictext", undefined, "内円の半径 (r):");
var rInput = dialog.add("edittext", undefined, "70");
rInput.characters = 5;
dialog.add("statictext", undefined, "ペンの距離 (d):");
var dInput = dialog.add("edittext", undefined, "100");
dInput.characters = 5;
dialog.add("statictext", undefined, "ステップ数:");
var stepsInput = dialog.add("edittext", undefined, "200");
stepsInput.characters = 5;
dialog.add("statictext", undefined, "回転数:");
var rotationsInput = dialog.add("edittext", undefined, "10");
rotationsInput.characters = 5;
var okButton = dialog.add("button",
        undefined, "OK", {name: "ok"});
var cancelButton = dialog.add("button",
        undefined, "キャンセル", {name: "cancel"});

var result = null;
okButton.onClick = function () {
result = {
R: parseFloat(RInput.text),
r: parseFloat(rInput.text),
d: parseFloat(dInput.text),
steps: parseInt(stepsInput.text, 10),
rotations: parseInt(rotationsInput.text, 10)
};
dialog.close();
};
cancelButton.onClick = function () {
result = null;
dialog.close();
};
dialog.show();
return result;
}

// メイン処理
function main() {
if (app.documents.length === 0) {
app.documents.add();
}
var doc = app.activeDocument;
var centerX = doc.artboards[0].artboardRect[2] / 2;
var centerY = doc.artboards[0].artboardRect[3] / 2;

var userInput = getUserInput();
if (!userInput) return;

drawSpirograph(doc, centerX, centerY, userInput.R, userInput.r,
        userInput.d, userInput.steps, userInput.rotations);
}

main();

実行して、各パラメーターの値を入力すれば描画が実行されます。パスの塊です。

パラメーター変更例(その1)

パラメーター変更例(その2)

パラメーター変更例(その3)

木曜日, 9月 11, 2025

Let's start JavaScript 82 
HTMLで複数の数値で作れる合計全表示

必要にせまられたので・・・
HTMLで複数の数値から作れる合計を重複を除きすべて表示させます。
例えば・・・
1,2,3の場合・・・ 1 2 3 1+3=4 2+3=5 1+2+3=6 となります。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>合計組み合わせ</title>
<style>
body {
font-family: sans-serif;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
background: black;
color: white;
}
input {
width: 200px;
padding: 5px;
}
</style>
</head>
<body>
<h3>複数の数値から作れる合計をすべて表示</h3>
<p>数値を入力してください(半角, 区切り):</p>
<span>
<input type="text" size="28" id="inputNumbers"
        value="7,14,28,9,16,30">
&ensp;
<button onclick="showSums()">合計を表示</button></span>
<h4>合計一覧(重複なし)</h4>
<div id="results"></div>
<script>
function showSums() {
const input = document.getElementById('inputNumbers').value;
const numbers = input.split(',').map(n =>
        parseInt(n.trim(), 10)).filter(n => !isNaN(n));
const resultSet = new Set();

const n = numbers.length;
for (let i = 1; i < (1 << n); i++) {
let sum = 0;
for (let j = 0; j < n; j++) {
if (i & (1 << j)) {
sum += numbers[j];
}
}
resultSet.add(sum);
}

const sortedSums =
        Array.from(resultSet).sort((a, b) => a - b);
document.getElementById('results').innerHTML =
        sortedSums.join(', ');
}
</script>
</body>
</html>



実行直後の画面。



デフォルト値のまま[合計を表示]をクリックすれば、複数の入力数値から作れる合計を重複を除きすべて表示します。



入力値はボックスに入力できるまで入れることが出来ます。

火曜日, 9月 09, 2025

JavaScriptでAI遊び 66 
Illustratorでオブジェクトを楕円へ均等配置(改訂版)

Illustratorで任意オブジェクトを楕円へ均等配置させます。前回の処理に回転設定の有無っを追加しました。

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

var doc = app.activeDocument;
var selection = doc.selection;

if (selection.length !== 2) {
alert("配置オブジェクト、楕円の順に選択してください。");
return;
}

var ellipse, object;
// 楕円とオブジェクトを特定
if (selection[0].typename ===
"PathItem" && selection[0].pathPoints.length > 3) {
ellipse = selection[0];
object = selection[1];
} else if (selection[1].typename ===
"PathItem" && selection[1].pathPoints.length > 3) {
ellipse = selection[1];
object = selection[0];
} else {
alert("楕円(パス)と配置するオブジェクトを選択してください。");
return;
}

// ユーザーに配置する数を入力させる
var count = parseInt(prompt
("楕円周上に配置するオブジェクトの数を入力:", "6"), 10);
if (isNaN(count) || count < 1) {
alert("正しい数値を入力してください。");
return;
}

// 回転の有無を選択
var rotateOption =
confirm("オブジェクトを楕円の角度に沿って回転させますか?");

// 楕円の中心座標とサイズを取得
var centerX = ellipse.position[0] + ellipse.width / 2;
var centerY = ellipse.position[1] - ellipse.height / 2;
var radiusX = ellipse.width / 2;
var radiusY = ellipse.height / 2;

var angleStep = 360 / count;

for (var i = 0; i < count; i++) {
var angle = angleStep * i * (Math.PI / 180);
var x = centerX + radiusX * Math.cos(angle);
var y = centerY + radiusY * Math.sin(angle);

var newObj = object.duplicate();
newObj.position =
[x - newObj.width / 2, y + newObj.height / 2];

if (rotateOption) {
newObj.rotate(angleStep * i);
}
}

alert("オブジェクトを均等配置しました!");
}

distributeObjectsOnEllipse();

配置するオブジェクトはグループ化されていても問題ありません。ここではシンボル登録したモノを利用しました。なお、楕円はオブジェクトの後に作成またはペーストします。

事項鵜したらオブジェクトの数と回転の有無を入力するだけです。

「オブジェクトを楕円の角度に沿って回転させますか?」で「はい」をクリックした結果。楕円での均等配置は3D視点での見た目で均等配置にしています。

「オブジェクトを楕円の角度に沿って回転させますか?」で「いいえ」をクリックした結果。

もちろん正円でも問題ありません。

木曜日, 9月 04, 2025

JavaScriptでAI遊び 65 
Illustratorでオブジェクトを楕円へ均等配置

Illustratorで任意オブジェクトを楕円へ均等配置させます。

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

var doc = app.activeDocument;
var selection = doc.selection;

if (selection.length !== 2) {
alert("配置オブジェクト、楕円の順に選択してください。");
return;
}

var ellipse, object;
// 楕円とオブジェクトを特定
if (selection[0].typename ===
"PathItem" && selection[0].pathPoints.length > 3) {
ellipse = selection[0];
object = selection[1];
} else if (selection[1].typename ===
"PathItem" && selection[1].pathPoints.length > 3) {
ellipse = selection[1];
object = selection[0];
} else {
alert("楕円(パス)と配置するオブジェクトを選択してください。");
return;
}

// ユーザーに配置する数を入力させる
var count = parseInt(prompt
("楕円周上に配置するオブジェクトの数を入力:", "6"), 10);
if (isNaN(count) || count < 1) {
alert("正しい数値を入力してください。");
return;
}

// 楕円の中心座標とサイズを取得
var centerX = ellipse.position[0] + ellipse.width / 2;
var centerY = ellipse.position[1] - ellipse.height / 2;
var radiusX = ellipse.width / 2;
var radiusY = ellipse.height / 2;

var angleStep = 360 / count;

for (var i = 0; i < count; i++) {
var angle = angleStep * i * (Math.PI / 180);
var x = centerX + radiusX * Math.cos(angle);
var y = centerY + radiusY * Math.sin(angle);

var newObj = object.duplicate();
newObj.position =
[x - newObj.width / 2, y + newObj.height / 2];
}

alert("オブジェクトを均等配置しました!(回転なし)");
}

distributeObjectsOnEllipseNoRotation();

配置するオブジェクトはグループ化されていても問題ありません。ここではシンボル登録したモノを利用しました。なお、楕円はオブジェクトの後に作成またはペーストします。

事項鵜したらオブジェクトの数を入力するだけです。

楕円での均等配置は3D視点での見た目で均等配置にしています。

もちろん正円でも問題ありません。

日曜日, 8月 31, 2025

JavaScriptでAI遊び 64 
Illustratorでカラー設定の明度を反転

特に目的は無いのですが、色相・彩度・明度の反転実験の明度版です。
CMYKでもRGBでも使えます。

function invertBrightness() {
var doc = app.activeDocument;
var selection = doc.selection;

if (selection.length === 0) {
alert("オブジェクトを選択してください。");
return;
}

for (var i = 0; i < selection.length; i++) {
var obj = selection[i];

if (obj.typename === "PathItem" && obj.filled) {
var color = obj.fillColor;

if (color.typename === "RGBColor") {
// RGBの明度を反転
color.red = 255 - color.red;
color.green = 255 - color.green;
color.blue = 255 - color.blue;

} else if (color.typename === "CMYKColor") {
// CMYKの明度を反転(K値の反転)
color.black = 100 - color.black;
}

obj.fillColor = color;
}
}
}

invertBrightness();

左からCMYKで・・・
ベースチャート、カラー反転、カラー反転を2回実行

左からCMYKで・・・
ベースチャート、明度反転、明度反転を2回実行

左からRGBで・・・
ベースチャート、カラー反転、カラー反転を2回実行

左からRGBで・・・
ベースチャート、明度反転、明度反転を2回実行

以下も参考にしてください

木曜日, 8月 28, 2025

Let's start JavaScript 81 
HTML上でランダムな斜線を描画

HTML上でランダムな色と太さの斜線を描画します。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport"
        content="width=device-width, initial-scale=1.0">
<title>ランダム斜め線描画</title>
<style>
body {
text-align: center;
font-family: Arial, sans-serif;
background-color: Black;
}
canvas {
border: 2px solid black;
margin-top: 10px;
background: white;
border: 1px solid white;
}
</style>
</head>
<body>

<h3>
    <font color="white">Random diagonal line drawing</font>
    </h3>
<label for="lineCount">線の本数:</label>
<input type="number" id="lineCount" value="10" min="1">
<button onclick="drawRandomLines()">描画</button>

<br>
<canvas id="canvas" width="500" height="500"></canvas>
<!-- canvas の width や height を変更すれば、
描画エリアを大きく or 小さくできます。 -->

<script>
function drawRandomLines() {
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const numLines = parseInt(document.
                getElementById("lineCount").value, 10);

if (isNaN(numLines) || numLines < 1) {
alert("正しい本数を入力してください!");
return;
}

// キャンバスをクリア
// ctx.globalAlpha = 0.5; を追加すると、
            // 半透明の線を描画できます。
ctx.clearRect(0, 0, canvas.width, canvas.height);

for (let i = 0; i < numLines; i++) {
// ランダムな開始点と終了点
let x1 = randomRange(0, canvas.width);
let y1 = randomRange(0, canvas.height);
let x2 = randomRange(0, canvas.width);
let y2 = randomRange(0, canvas.height);

// ランダムな線の太さ
let lineWidth = randomRange(1, 15);
// randomRange(1, 15); の範囲を変更すると、
// 線の太さを太く or 細く 調整可能。

// ランダムなRGBカラー
let color = `rgb(${randomRange(0, 255)},
${randomRange(0, 255)}, ${randomRange(0, 255)})`;

// 線を描画
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.lineWidth = lineWidth;
ctx.strokeStyle = color;
ctx.stroke();
}
}

// min~maxの範囲でランダムな数を生成
function randomRange(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
</script>
</body>
</html>

実行北後の画面です。数値(デフォルトは10)を入力して[描画]をクリックすれば・・・

枠内に表示されます。

100で実行した結果。

日曜日, 8月 24, 2025

JavaScriptでAI遊び 63 
Illustratorでカラー設定の彩度を反転

特に目的は無いのですが、色相・彩度・明度の反転実験の彩度版です。
CMYKでもRGBでも使えます。

#target illustrator

function invertSaturation() {
var doc = app.activeDocument;
var selection = doc.selection;

if (!selection.length) {
alert("オブジェクトを選択してください。");
return;
}

for (var i = 0; i < selection.length; i++) {
var obj = selection[i];

if (obj.typename === "PathItem") {
// 塗りの色を処理
if (obj.filled) {
obj.fillColor = invertSaturationColor(obj.fillColor);
}
// 線の色を処理
if (obj.stroked) {
obj.strokeColor = invertSaturationColor(obj.strokeColor);
}
}
}

alert("選択したオブジェクトの彩度を反転しました。");
}

// 色の彩度を反転する関数
// RGBカラー:彩度(Saturation)を 100 - 現在の彩度 に変更
function invertSaturationColor(color) {
if (color.typename === "RGBColor") {
var hsb = rgbToHsb(color.red, color.green, color.blue);
hsb[1] = 100 - hsb[1]; // 彩度を反転
var newRgb = hsbToRgb(hsb[0], hsb[1], hsb[2]);

var newColor = new RGBColor();
newColor.red = newRgb[0];
newColor.green = newRgb[1];
newColor.blue = newRgb[2];
return newColor;

} else if (color.typename === "CMYKColor") {
// CMYKでの彩度反転(簡易的に補色を利用)
// CMYKカラー:
        // 補色の考え方を利用し、C, M, Y の値を反転(K はそのまま)
var newColor = new CMYKColor();
newColor.cyan = 100 - color.cyan;
newColor.magenta = 100 - color.magenta;
newColor.yellow = 100 - color.yellow;
newColor.black = color.black; // 黒は変更しない
return newColor;
}

return color; // 変更なし
}

// RGB → HSB 変換
function rgbToHsb(r, g, b) {
r /= 255; g /= 255; b /= 255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, v = max;

var d = max - min;
s = max === 0 ? 0 : d / max;

if (max === min) {
h = 0;
} else {
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h *= 60;
}
return [h, s * 100, v * 100];
}

// HSB → RGB 変換
function hsbToRgb(h, s, v) {
s /= 100; v /= 100;
var c = v * s;
var x = c * (1 - Math.abs((h / 60) % 2 - 1));
var m = v - c;

var r, g, b;
if (h < 60) { r = c; g = x; b = 0; }
else if (h < 120) { r = x; g = c; b = 0; }
else if (h < 180) { r = 0; g = c; b = x; }
else if (h < 240) { r = 0; g = x; b = c; }
else if (h < 300) { r = x; g = 0; b = c; }
else { r = c; g = 0; b = x; }

return [(r + m) * 255, (g + m) * 255, (b + m) * 255];
}

// スクリプト実行
invertSaturation();
// RGBでは補色、CMYKでは黒の値が反転されるため、効果が異なります

左からCMYKで・・・
ベースチャート、カラー反転、カラー反転を2回実行

左からCMYKで・・・
ベースチャート、彩度反転、彩度反転を2回実行

左からRGBで・・・
ベースチャート、カラー反転、カラー反転を2回実行

左からRGBで・・・
ベースチャート、彩度反転、彩度反転を2回実行