ワタタクどうも上達の研究家のワタタクです。
「Linked Log: L-001」で誕生した包絡線。それを単なる「図形」で終わらせず、画面全体を彩る「アート」へと昇華させるための技術実験、それが今回の記事です。
技術の核心:発見(Discovery)のポイント
このコードには、初心者が中級者へと上達するための「3つの賢い工夫」が隠されています。
| 工夫のポイント | 技術の内容 | 得られる表現効果 |
| ランダム配置 | random(width/height) | 画面にリズムと「自然なばらつき」を生みます。 |
| 動的な密度設計 | map(r, 50, 250, 8, 20) | 大きな図形は緻密に、小さな図形はシンプルに。画面のバランスを自動で整えます。 |
| 独自関数のカプセル化 | drawEnvelope() | 複雑な計算を一つの「部品(関数)」にまとめることで、量産を楽にします。 |
たくさんの包絡線をランダムに配置するコード


実行する度に、位置や大きさが変わります。
Processing版
デスクトップ環境で高画質な画像を生成するためのコードです。背景色にわずかなベージュ(245, 243, 240)を混ぜることで、デジタルでありながら「画用紙」のような温かみを演出しています。
void setup() {
size(1600, 900);
background(245, 243, 240); // 画用紙風の背景
noLoop();
smooth();
// 図形の個数(ここを変えると描画される数が増減します)
int numShapes = 50;
for (int i = 0; i < numShapes; i++) {
// ランダムな位置とサイズを決める
float x = random(width); // 画面の横幅のどこか
float y = random(height); // 画面の縦幅のどこか
float r = random(50, 250); // 半径は50px〜250pxの間でランダム
// サイズに合わせて線の密度(分割数)を調整
// 大きい図形は線を多く、小さい図形は線を少なくすると綺麗に見えます
int lines = int(map(r, 50, 250, 8, 20));
// 独自関数を呼び出して描画
drawEnvelope(x, y, r, lines);
}
}
// 包絡線を1つ描くための関数
// x, y: 中心座標, r: 半径, numLines: 分割数
void drawEnvelope(float x, float y, float r, int numLines) {
pushMatrix(); // 座標の状態を保存(この図形のためだけに座標を動かす)
translate(x, y); // 指定された位置(x, y)を原点(0, 0)にする
// 線の設定(少し透明度を入れて、重なった時に綺麗に見えるようにする)
stroke(50, 150); // グレー, 透明度150
strokeWeight(1);
// 軸を描く(画面全体ではなく、図形のサイズ分だけ描く)
line(-r, 0, r, 0);
line(0, -r, 0, r);
// 4つの象限を描画
for (int i = 0; i <= numLines; i++) {
float a = map(i, 0, numLines, 0, r);
float b = map(i, 0, numLines, r, 0);
// 右上
line(0, -a, b, 0);
// 左上
line(0, -a, -b, 0);
// 右下
line(0, a, b, 0);
// 左下
line(0, a, -b, 0);
}
// 目盛り(点)の描画
strokeWeight(3);
for (int i = 0; i <= numLines; i++) {
float p = map(i, 0, numLines, 0, r);
point(p, 0);
point(-p, 0);
point(0, p);
point(0, -p);
}
popMatrix(); // 座標の状態を元に戻す(次の図形のためにリセット)
}p5.js版
Processingのロジックをウェブでも見れるようにしたp5.jsバージョンです。iPhone 17 Pro Maxを使ってp5.js Web editorで動作確認済み。
push() と pop() を使うことで、複雑な座標計算をスマートに処理。
function setup() {
createCanvas(1600, 900); // size() の代わりに createCanvas()
background(245, 243, 240); // 画用紙風の背景色
noLoop(); // 静止画なので描画ループを止める
// 図形の個数
let numShapes = 50;
for (let i = 0; i < numShapes; i++) {
// ランダムな位置とサイズを決める
let x = random(width);
let y = random(height);
let r = random(50, 250); // 半径
// サイズに合わせて線の密度(分割数)を調整
// p5.jsでも int() 関数で小数点以下を切り捨てられます
let lines = int(map(r, 50, 250, 8, 20));
// 独自関数を呼び出して描画
drawEnvelope(x, y, r, lines);
}
}
// 包絡線を1つ描くための関数
function drawEnvelope(x, y, r, numLines) {
push(); // Processingの pushMatrix() / pushStyle() に相当
translate(x, y); // 原点を (x, y) に移動
// 線の設定
stroke(50, 150); // 色50(濃いグレー), 透明度150
strokeWeight(1);
// 軸を描く
line(-r, 0, r, 0);
line(0, -r, 0, r);
// 4つの象限を描画
for (let i = 0; i <= numLines; i++) {
let a = map(i, 0, numLines, 0, r);
let b = map(i, 0, numLines, r, 0);
// 右上
line(0, -a, b, 0);
// 左上
line(0, -a, -b, 0);
// 右下
line(0, a, b, 0);
// 左下
line(0, a, -b, 0);
}
// 目盛り(点)の描画
strokeWeight(3);
for (let i = 0; i <= numLines; i++) {
let p = map(i, 0, numLines, 0, r);
point(p, 0);
point(-p, 0);
point(0, p);
point(0, -p);
}
pop(); // Processingの popMatrix() / popStyle() に相当
}一(One)が全(All)へ広がる瞬間
今回のコードで最も美しいのは、「サイズ(半径r)に応じて線の本数(numLines)が変わる」という設計です。
これは、マクロな視点(大きな図形)とミクロな視点(小さな図形)を一つのルールで統括する「一は全、全は一」の思想を数学的に表現したものです。
Processingの14行目のfloat r = random(50, 250);。p5.jsの13行目のlet r = random(50, 250); // 半径の250の部分を500に変えると包絡線も大きくなって、手描きで重ねて包絡線を描いたらどうなるのかをイメージしやすい。
終わりに:レッツ・ワクワク・コーディング!
このコードをコピーして、numShapes(個数)や stroke(透明度)の数値を変えてみてください。それだけで、あなただけの「Pixel Jewel」が画面に現れるはずです。
「こう書けば、こうなる」という発見こそが、上達の最短ルートです。



それでは今日もレッツワクワクコーディング。
包絡線の基本を知りたい方は以下の記事へ。



