そのWeb演出、Claude Codeで作れます。クリエイティブWeb表現のプロンプト集 #10 Straightedge & Compass
株式会社グルーヴサインの米沢です。
AIコーディングでクリエイティブなWeb表現を実際に作り、そのプロンプトごと公開していく「PROMPT → WEB」の第10回です。
PROMPT → WEB #010
Straightedge & Compass
INTRODUCTION
前回(#09)の最後に、次は「幾何の証明が組み上がっていく線」と書きました。今回がそれです。
これまでの9回は、どれも見た目をどう作るかの話でした。今回だけは少し性格が違って、主役は正しさです。
題材は、定規とコンパスによる作図。2300年ほど前に『原論』で整理された手続きで、使える操作はたった3つしかありません。
① 与えられた2点を通る直線を引く
② 与えられた中心と半径で円を描く
③ すでに引いた線どうしの交点を取る
この3つだけで、正三角形も、正方形も、正六角形も、そして正五角形も描けます。五角形というのが面白いところで、頂点の位置は 72° ずつですが、作図では角度を一度も測りません。 円と円の交点を取っていくうちに、勝手に72°になります。
今回のコードには Math.cos も Math.sin も、頂点を求める場所には1行も出てきません。 出てくるのは交点の計算だけです。それで本当に正しい正五角形になる、というのを画面で見てもらうのが今回の趣旨です。
RESULT
まず現物です。下のボタンを押してみてください。
クリックすると、この画面の上で Straightedge & Compass が再生されます(何度でも再生可能)。ESC または CLOSE で終了します。
暗い紫紺の空間に、金色の円がひとつ描かれるところから始まります。コンパスの弧が光跡を引いて走り、交点が星のようにきらめき、最後に図形が結ばれて明滅します。描いている先端からは光の粒が散り、完成の瞬間には頂点から光が弾けます。画面下に、いま何をしているかの手順が出ます。操作は2つです。
- カーソルを動かす(スマホは画面をなぞる) ── 円周上の点 P が動きます。作図全体がその場で引き直されます。 録画した動画ではないことが、これで分かると思います。
- クリックする(スマホはタップ) ── 次の図へ。正三角形 → 正方形 → 正六角形 → 正五角形。
しばらく触らずにいると、点 P がひとりでにゆっくり回り、作図が繰り返されます。ESC または CLOSE で終了します。
WHAT WE MADE
技術的に分解すると、次のようになります。
- 幾何の核は3つの関数だけ ── 円と円、直線と直線、直線と円。交点を求めるこの3つで全部が成り立っています。
- 垂直二等分線 ── 作図の基本動作。中点も直角も、ここからしか出てきません。
- 作図を手順のデータとして持つ ── 「円を描く」「交点を取る」といった手順の配列を組み立て、描画はそれを順に描くだけ。
- 三角関数を使わない頂点 ── 正五角形の一辺の長さを、円と直線の交点から導きます(後述)。
- 光で引く線 ── 1本の線を「外側の滲み・中間・芯」の3枚に分けて加算合成で重ね、発光させています。
- 光の粒 ── コンパスの先端から火花が散り、完成時には頂点から弾け、何もしていない間も空気がゆっくり光ります。
- 静止フォールバック ── アニメーションを好まない設定では、完成した正五角形を1枚だけ描きます。
HOW IT WORKS
1. 円と円の交点
いちばん使うのがこれです。2つの円の中心と半径から、交点を求めます。
function circleCircle(c1, r1, c2, r2) {
const d = dist(c1, c2);
if (d < 1e-9 || d > r1 + r2 + 1e-9 || d < Math.abs(r1 - r2) - 1e-9) return [];
const a = (r1 * r1 - r2 * r2 + d * d) / (2 * d); // 中心線に沿った距離
const h = Math.sqrt(Math.max(0, r1 * r1 - a * a)); // そこからの垂線の長さ
const px = c1.x + a * (c2.x - c1.x) / d;
const py = c1.y + a * (c2.y - c1.y) / d;
return [{ x: px - h * (c2.y - c1.y) / d, y: py + h * (c2.x - c1.x) / d },
{ x: px + h * (c2.y - c1.y) / d, y: py - h * (c2.x - c1.x) / d }];
}
離れすぎ・近すぎの判定を省くと Math.sqrt が NaN を返し、そこから先の作図が静かに全部壊れます。交点が「無い」場合があることを、最初に書いておくのが大事です。
2. 垂直二等分線が、すべての基本
2点 A・B から等距離の点の集まりが、垂直二等分線です。作図では、A と B を中心に同じ半径の円を描き、その2つの交点を結ぶだけで引けます。
これが引けると、中点(二等分線と線分ABの交点)と直角(二等分線そのもの)が手に入ります。今回の正方形も正五角形も、出発点はここです。
3. 正五角形の一辺を、角度を使わずに出す
いちばんの山場です。半径 r の円に内接する正五角形の一辺は 2r·sin36° ですが、作図ではこの式を使いません。代わりにこうします。
① 円の中心 O、円周上の点 A(上)
② A を通る直径を引き、反対側の交点 A' を取る
③ AA' の垂直二等分線を引き、円との交点 Q を取る(=直角が手に入る)
④ OQ の垂直二等分線から、OQ の中点 M を取る
⑤ M を中心に、半径 MA の円を描く
⑥ その円が直径 QQ' を切る点 N を取る
⑦ 線分 AN の長さが、正五角形の一辺
本当にそうなるのか、数値で確かめました。半径1で計算すると、
求めた一辺 AN 1.175570505
2·sin(36°) 1.175570505 ← 誤差 0.00e+0
一致します。あとはこの長さをコンパスに取り、円周を5回刻めば5頂点です。刻んだ結果の各辺を測ると、5本とも 352.6712(半径300pxのとき)で揃い、最後の点が最初の点にぴったり戻ります。角度を一度も計算していないのに、72°ずつ並んでいるわけです。
4. 交点は2つ出る ── どちらへ進むかを決める
円周をコンパスで刻むとき、円と円の交点は毎回2つ出ます。片方は進みたい方向、もう片方は1つ前に戻る方向です。素直に書くと、行って戻ってを繰り返して図形が閉じません。
進行方向は外積の符号で決めました。中心から見て、いまの点から左回りか右回りかを判定しています。
const cross = (z) => (from.x - O.x) * (z.y - O.y) - (from.y - O.y) * (z.x - O.x);
return candidates.sort((p, q) => cross(q) - cross(p))[0];
作図の本には「順に取っていく」としか書かれていない部分で、コードにするとここが一番引っかかります。
5. 手順をデータとして持つ
作図を手続きのコードとして書くのではなく、描くものの配列として組み立てています。
steps.push({ kind: 'circle', c: M, r: dist(M, A), aux: true, cap: 'M を中心に半径 MA の円を描く' });
steps.push({ kind: 'point', p: N, name: 'N', cap: '直径との交点 N を取る' });
この形にしておくと、順番に途中まで描く(=アニメーション)、いまの手順を説明文として出す、手順数を数えるが、全部ただで手に入ります。描画側は配列を順に描くだけで、作図の中身を知る必要がありません。
6. 光に見せる
線をそのまま引くと、ただの図形です。発光させるのに filter: blur() のような重い手は使わず、同じ線を3回、太さと濃さを変えて加算合成で重ねています。
const passes = [[6.5, 0.085], [2.6, 0.22], [1, 1]]; // [太さ倍率, 濃さ倍率]
ctx.globalCompositeOperation = 'lighter';
for (const [wm, am] of passes) { /* 同じ線を引く */ }
外側の太く薄い1枚が滲み、芯の1枚が明るく締まる。これだけで線が光って見えます。交点の印も、放射グラデーションに十字のきらめきを足しただけです。
線には、ごくわずかな揺らぎも入れています。ここで注意が要りました。揺れを毎フレーム乱数で引き直すと、線が小刻みに波打ちます。 位置と線の番号から決まる固定のハッシュを使い、同じ線なら常に同じ揺れになるようにしています。
const hash = (i, seed) => {
const x = Math.sin(i * 127.1 + seed * 311.7) * 43758.5453;
return (x - Math.floor(x)) * 2 - 1;
};
7. 見た目を差し替えても、幾何は1行も変わらない
最初に作ったとき、この作品は黒板とチョークでした。白い線、緑の板、粉っぽい質感。作図の記録としては悪くなかったのですが、見ていて心が躍るかというと、そうでもない。
そこで魔法陣に変えました。このとき、幾何のコードは1行も触っていません。
手順3で書いたとおり、作図は「描くものの配列」として組み立ててあります。描画側は配列を順に描くだけなので、chalkPath() を glowPath() に差し替え、色を決め直し、光の粒を足しただけで終わりました。作図と描画が分かれていると、見た目の作り直しが怖くなくなります。
考えてみれば、魔法陣はもともと定規とコンパスの作図です。描いているものは最初から同じでした。
THE PROMPT
ここが本題です。上のデモを作るためにClaude Codeへ渡せる、汎用プロンプト全文を掲載します。右上の COPY ボタンでそのままコピーできます。
あなたは計算幾何とCreative Codingに精通したフロントエンドエンジニアです。
「Straightedge & Compass」= 光の魔法陣として、定規とコンパスだけの操作から正多角形が
組み上がっていく表現を、Canvas 2D で実装してください。
(幾何ライブラリは使わない。交点の計算は自前で書く)
# 最重要の制約
- 使ってよい操作は3つだけ: 直線を引く / 円を描く / すでに引いた線どうしの交点を取る
- 【厳守】正多角形の頂点を三角関数で求めないこと。
Math.cos / Math.sin で頂点を並べるのは作図ではない。
頂点は必ず「円と円の交点」「直線と円の交点」として導くこと
(円弧を描画する時だけは cos/sin を使ってよい。あくまで頂点の導出の話)
# 置き換える変数
- GROUND = "#140c1d" // 深い紫紺の夜
- INK = "#ffe9b8" // 光で引く線
- AUX = "rgba(236,200,130,0.30)" // 補助線は淡い金
- 仕上げの図形は作図ごとに色を変える:
正三角形 "#ffd98a" / 正方形 "#ff9fc4" / 正六角形 "#8ef0d8" / 正五角形 "#c9a6ff"
- LABEL = "STRAIGHTEDGE & COMPASS"
# 幾何の核(この3つだけ書けばよい)
- circleCircle(c1,r1,c2,r2) … 離れすぎ/近すぎ/同心を必ず弾く。弾かないとNaNが伝播して
以降の作図が静かに全部壊れる
- lineLine(a,b,c,d) … 平行は null を返す
- lineCircle(a,b,c,r) … 判別式が負なら空配列
- bisector(a,b) … 垂直二等分線。a,b を中心に半径|ab|の円を2つ描き、その交点2つを返す。
中点も直角も、すべてここから導く
# 4つの作図(クリックで切り替え)
1. 正三角形 … 同じ半径の2円の交点
2. 正方形 … 直径と、その垂直二等分線が円を切る2点
3. 正六角形 … 半径をそのままコンパスに取り、円周を刻む(半径=一辺)
4. 正五角形 … ①直径AA' ②AA'の垂直二等分線→円との交点Q ③OQの中点M
④M中心・半径MAの円が直径を切る点N ⑤線分ANが一辺 ⑥ANで円周を5回刻む
- 【注意】円周を刻むとき交点は毎回2つ出る。進行方向を外積の符号で選ばないと
行ったり来たりして図形が閉じない
# 作図は「手順のデータ」として持つ
- { kind:'circle'|'line'|'point'|'figure', …座標…, aux:bool, cap:'この手順の説明' } の配列を作る
- 描画側は配列を順に描くだけにする。こうすると、途中まで描くアニメーション・
手順の説明表示・手順数の表示が、追加の実装なしで手に入る
# 描画(光の魔法陣)
- 線は発光させる。filter:blur は使わず、同じ線を3回重ねる:
[太さ×6.5, 濃さ×0.085] → [×2.6, ×0.22] → [×1, ×1]、合成は 'lighter'
- 線にごくわずかな揺らぎを入れる。
【罠】揺れを毎フレーム乱数で引き直すと線が小刻みに波打つ。
点の番号と線の番号から決まる固定のハッシュを使い、同じ線は常に同じ揺れにすること
- 補助線は淡い金で薄く、仕上げの図形だけ太く鮮やかに。完成後はゆっくり明滅させる
- 交点は「放射グラデ+十字のきらめき」で星のように光らせ、記号(A, B, M, N …)を添える
- 【注意】補助点の記号と頂点の記号を衝突させない(同じ図に B が2つ出ると読めなくなる)
- 光の粒を散らす: ①描いている先端から火花 ②完成の瞬間に頂点から弾ける
③何もしていない間も、ゆっくり漂う粒を少しずつ足して空気を光らせる
- 背景は作図の中心から立ちのぼる紫のオーラと、周辺光量落ち、ごく薄い粒子
- 画面下に、いまの手順の説明文を明朝系で1行
# インタラクション
- ポインタを動かすと円周上の点Pが動き、【作図全体をその場で引き直す】。
毎フレーム全部やり直しても計算は数マイクロ秒で済む(録画でないことが伝わる)
- クリック/タップで次の作図へ。手順は最初から再生する
- 数秒操作が無ければ、点Pをゆっくり回して作図を繰り返す
# 品質要件(production)
- 全画面オーバーレイ。CLOSE ボタンと ESC で終了。多重起動を防ぐ
- レスポンシブ: リサイズで座標を組み直す。devicePixelRatio は最大2でクランプ
- prefers-reduced-motion: アニメーションせず、完成した図を1枚だけ描いて静止させる
- 終了時に requestAnimationFrame を停止し、全リスナを解除し、CanvasをDOMから除去する
- Canvas 2D が使えない環境では静かに何もしない。本文の閲覧を妨げない
CUSTOMIZE
- 作図を足す ── 手順の配列を返す関数を1つ書き足すだけで増やせます。正八角形(正方形の各辺の垂直二等分線)、黄金長方形、放物線の接線あたりが手頃です。
- 見た目ごと変える ── 描画関数は作図から切り離してあるので、差し替えは容易です。実際この作品は黒板とチョークから作り直しました。地を生成りの紙、線を製図インクにして揺れを0にすれば、そのまま数学書の図版になります。
- 光の量 ── 重ねる3枚の太さと濃さ。外側を太くすると幻想的に、細くすると硬質なネオンになります。
- 手順の速さ ── 1秒あたり何手順進むか。遅くすると講義の板書、速くすると一気に組み上がる演出になります。
- 補助線を残すか消すか ── 描き終えた補助線の濃さ。濃く残すと「作図の記録」、薄く消すと「結果だけ」の見え方になります。
- 記号 ── A・B・M・N の付け方。記号を消すと純粋な図形に、増やすと教科書の挿図に寄ります。
PERFORMANCE
今回は、計算より描画のほうが重いという珍しい回です。
- 作図の計算は無視できる ── 正五角形を丸ごと作図し直すのに 1.27µs(Node実測)。60fpsの1フレーム予算に対して 0.008% です。だからポインタを動かすたび、毎フレーム全部を引き直しても何の問題もありません。「動かしても追従する」という手応えが、そのまま「本物の作図である」という説得力になります。
- 重いのは発光 ── 1本の線につき3回引くので、描画回数は見た目の3倍です。手順が20を超える正五角形では、ここが支配的になります。
filter: blur()を使えば1回で済みますが、毎フレーム全画面にかけると桁違いに重くなるため、重ね描きのほうが結果的に安上がりです。 - 光の粒は上限で止める ── 同時に存在する粒を420個で打ち切り、古いものから捨てています。放っておくと増え続けるのがこの手の実装の定番の事故です。
- 円弧は進捗に応じて分割数を変える ── 描き始めの短い弧を44分割しても意味がないので、進捗に比例させています。
- 後始末 ── 終了時にRAFを停止し、全リスナを解除してCanvasを除去。開閉を繰り返してもリークしません。
WHAT AI DID / WHAT HUMAN DIRECTION MATTERS
幾何の公式そのものは、AIの得意分野です。円と円の交点も、垂直二等分線も、正五角形の作図手順も、聞けば正確に返ってきます。 境界条件(離れすぎた円、平行な直線)の処理まで含めて、ここは完全にAIの領分でした。
ただ、何も指定しないとAIは頂点を三角関数で並べます。 それはそれで正しい正五角形が描けるので、画面だけ見れば区別がつきません。しかしそれは作図ではなく、今回の記事は成立しません。
ですから今回の人間の仕事は、ほとんどが制約を課すことでした。
- 「
Math.cosで頂点を出してはいけない」という縛りを最初に宣言すること - 交点が2つ出たときにどちらへ進むかを、外積で決めると判断すること
- 補助点の記号と頂点の記号が衝突していることに気づくこと(最初の版は、同じ図の中に
Bが2つありました) - チョークの揺れを毎フレーム引き直さず、固定のハッシュにすること
- 最初に作った黒板版を「正しいが心が躍らない」と判断し、作り直すと決めたこと(作図と描画を分けてあったので、幾何には一切触らずに済みました)
- そもそも「正しさを見せる」という題材を選ぶこと
面白いのは、縛りを入れたほうがコードが短くなったことです。三角関数で頂点を並べる実装より、交点だけで組み立てる実装のほうが、関数が3つで済みました。制約は窮屈にするものだと思われがちですが、設計を決めてくれることのほうが多い。AIに何を禁じるかが、そのまま作品の輪郭になるという回でした。
NEXT
粒子、文字、線、物理、計算、製版、音、分割、光と影、そして今回の作図。ちょうど10回になりました。
次回はスクロール連動か、歪像(ある一点から見たときだけ像を結ぶ絵)あたりを考えています。
今回のプロンプトも丸ごとコピーして使えます。色を自社のブランドカラーに置き換えて、Claude Codeに渡してみてください。角度を測らずに五角形が閉じる瞬間は、何度見ても気持ちがいいものです。
レガシーPHPシステムの保守・引き継ぎのご相談を受け付けています。
初回のご相談・ヒアリングは無料です。