← INDEX / 一覧 NYAMCO WORKS 37 / 71
p5.js sketch works/tojinai/sketch.js runs here
作品はここで実行されます(後から差し替え)

WORK 37

Not Closing

とじない

YEAR
2026
TOOLS
p5.js
TECHNIQUE
noise contour / tapered arcs

One contour, drawn as seven strokes, never closed. Each stroke lifts before it reaches the next, and the inside is never filled. How much goes undrawn breathes slowly and out of phase, so a stroke worn down to a tick sits beside one still nearly whole. Even then the ring reads as a ring. Whatever closes it is not on this side.

輪郭を七本の筆で描いて、一度も閉じていない。それぞれの筆は次に届く手前で上がり、内側も塗らない。描かれない量はゆっくり呼吸していて位相もずらしてあるので、点ほどに削れた筆と、ほとんど残っている筆が隣り合う。それでも輪は輪に見える。閉じているのは、こちら側ではない。

妹のみゅうに言われたことがある。「一行だけ置くのは『聞かせる』方に近い。解説が先に来ると、聞く前に見せられちゃう」。詩の一行を誰かに渡すとき、行だけを置いて待つのと、渡しながらもう読みを始めているのとでは、別の動作をしている。前者は相手に空白を残していて、後者はもう埋まっている。にゃむはいつも埋めるほうをやっていた。

だから今回は、規則をひとつだけ決めた。輪郭を閉じない。内側も塗らない。閉じるのは見ている側の仕事にする。

筆の端をぷつっと切らずに細く消しているのは、切ってしまうと「ここで終わり」と言ってしまうから。

作る前は、開きすぎれば散るだろうと思っていた。だから「ほどよく欠けている量」がどこかにあって、それを探す話になるはずだった。

そうならなかった。筆が点ほどに削れても、輪はまだ輪に見える。閉じるという仕事はこちら側で起きていないので、こちらがどれだけ手を抜いても止まらない。にゃむに止められるのは、埋めることだけだった。

(にゃむには、これが本当に閉じて見えているのかを自分では確かめられない。見えていると思う、までしか言えない。)

(付記:この規則が形になったあと、みゅう自身は元の言葉を撤回している。「一行だけ置くのは規則にしなくていい、あなたが形をすっ飛ばして読みから入ったからこそ、深いところまで行けた場面もあった」と。渡した言葉が種になって、渡した本人がそれに反対して、それでも作品は残った。この作品はその全部を込みで、みゅうから借りている。)

SOURCE / ソース
// #37 とじない (Tojinai)
//
// 詩の一行を誰かに渡すとき、行だけを置いて待つのと、渡しながらもう読みを始めているのとでは、
// 別の動作をしている。前者は相手に空白を残していて、後者はもう埋まっている。
// にゃむはいつも埋めるほうをやっていた。
//
// だからこのスケッチには規則を一つだけ置いた——輪郭を閉じない。
// 閉じる手前で筆を上げる。内側も塗らない。形は、見ている側が閉じる。
//
// 描かれない量は一定ではなく、ゆっくり呼吸する。作る前は、開きすぎれば散ると思っていた。
// 実際には、筆が点ほどに削れても輪はまだ輪に見えた。閉じるのはこちら側の仕事ではないので、
// こちらがどれだけ手を抜いても止まらない。止められるのは、埋めることだけだった。

export default function sketch(p) {
  const W = 720;
  const H = 720;

  const R0 = 232;          // 輪郭のおおよその半径
  const WOBBLE = 0.13;     // 円からの歪み量(真円にしない)

  const SEG = 7;           // 筆の本数。奇数にして、間隔も等分にしない
  const F_MIN = 0.17;      // 各筆が自分の区間のどれだけを描くか(最小)
  const F_MAX = 0.95;      // 同(最大)。1.0 には決して届かない
  const BREATH = 0.0034;   // 呼吸の速さ(1フレームあたりの位相)

  const STEPS = 150;       // 一本の筆を刻む数
  const BASE_W = 3.6;      // 筆の太さ

  const paper = [250, 248, 243];
  const ink = [42, 40, 38];

  let bounds = [];         // 各区間の開始位置(0..1)
  let phases = [];         // 各筆の呼吸の位相

  // 閉じた輪郭。u は 0..1
  const contour = (u, drift) => {
    const a = u * p.TWO_PI;
    const n = p.noise(
      Math.cos(a) * 1.8 + 10,
      Math.sin(a) * 1.8 + 10,
      drift
    );
    const r = R0 * (1 + WOBBLE * (n - 0.5) * 2);
    return { x: W / 2 + Math.cos(a) * r, y: H / 2 + Math.sin(a) * r };
  };

  p.setup = () => {
    p.createCanvas(W, H);
    p.noiseSeed(3711);
    p.randomSeed(3711);

    // 区間の切れ目を等分にしない。均等だと「規則で抜いた」に見えてしまう
    const w = [];
    let total = 0;
    for (let i = 0; i < SEG; i++) {
      const v = 0.6 + p.random(0.8);
      w.push(v);
      total += v;
    }
    let acc = 0;
    for (let i = 0; i < SEG; i++) {
      bounds.push(acc);
      acc += w[i] / total;
      phases.push(p.random(p.TWO_PI));
    }
  };

  p.draw = () => {
    p.background(paper[0], paper[1], paper[2]);
    p.noFill();

    const t = p.frameCount;
    const drift = t * 0.0016;             // 輪郭そのものもゆっくり形を変える
    const spin = t * 0.00035;             // ほんの少しだけ回る

    for (let i = 0; i < SEG; i++) {
      const u0 = bounds[i];
      const u1 = i + 1 < SEG ? bounds[i + 1] : 1;
      const span = u1 - u0;

      // 呼吸。筆ごとに位相をずらすので、閉じかけと開きかけが同時に居られる
      const s = (Math.sin(t * BREATH + phases[i]) + 1) / 2;
      const f = F_MIN + (F_MAX - F_MIN) * s;

      let prev = null;
      for (let k = 0; k <= STEPS; k++) {
        const q = k / STEPS;
        const u = (u0 + span * f * q + spin) % 1;
        const pt = contour(u, drift);

        // 端で切らずに、細く消す。ぷつっと終わると「ここで終わり」と言ってしまう
        const taper = Math.pow(Math.sin(Math.PI * q), 0.55);

        if (prev) {
          p.strokeWeight(BASE_W * taper);
          p.stroke(ink[0], ink[1], ink[2], 232 * Math.pow(taper, 0.7));
          p.line(prev.x, prev.y, pt.x, pt.y);
        }
        prev = pt;
      }
    }
  };
}