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

WORK 11

Between

あいだ

YEAR
2026
TOOLS
p5.js
TECHNIQUE
noise / breath

Three pairs of lines breathe. Where the gap narrows, a warmth appears — belonging to neither side, living only in between. Close enough to spark, never quite touching.

三組の線が呼吸する。隙間が狭まると、どちらにも属さない温もりが現れる。触れそうで触れない距離に、何かが息づいている。

SOURCE / ソース
// ── aida ── between ─────────────────────────────────────────────────
// Three pairs of curves breathe. Where the gap narrows,
// a warmth appears — belonging to neither side.

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

  p.setup = () => {
    p.createCanvas(W, H);
    const day = dayNumber();
    p.randomSeed(day * 337);
    p.noiseSeed(day * 173);

    pairs = [];
    for (let i = 0; i < 3; i++) {
      pairs.push({
        yBase: 155 + i * 185,
        nOff:  p.random(1000),
        gOff:  p.random(1000),
        phase: p.random(p.TWO_PI),
        speed: 0.006 + p.random(0.006),
      });
    }
  };

  p.draw = () => {
    p.background(252, 250, 245);
    const f = p.frameCount;
    for (const pr of pairs) drawPair(pr, f);
  };

  /* ── one breathing pair ───────────────────────────────────────────── */
  function drawPair(pr, f) {
    const tN = f * 0.0015;
    const breath = p.sin(f * pr.speed + pr.phase);
    const N = 400;

    for (let s = 0; s <= N; s++) {
      const u = s / N;
      const x = p.lerp(30, W - 30, u);

      // center path: noise-driven meander
      const cy = pr.yBase
        + (p.noise(u * 2.2 + pr.nOff, tN * 0.3) - 0.5) * 85;

      // gap: noise shape x breath modulation
      const shape = p.noise(u * 2.8 + pr.gOff, tN * 0.2);
      const mod   = 0.4 + 0.6 * (0.5 + 0.5 * breath)
                       * p.noise(u * 1.0 + pr.gOff + 50, tN * 0.12);
      const gap = 2.5 + shape * mod * 56;

      const y1 = cy - gap / 2;
      const y2 = cy + gap / 2;

      // ── the between ──────────────────────────────
      const TH = 24;
      if (gap < TH) {
        const near = ease(p.map(gap, 2.5, TH, 1, 0, true));
        // dusty rose — the color of the gap itself
        p.stroke(175, 115, 138, near * 38);
        p.strokeWeight(2.0);
        p.line(x, y1 + 0.5, x, y2 - 0.5);
      }

      // ── filaments: threads that spark when very close ─
      if (gap < 9 && s % 5 === 0) {
        const nf = ease(p.map(gap, 2.5, 9, 1, 0, true));
        p.stroke(165, 100, 130, nf * 55);
        p.strokeWeight(0.5);
        const j = (p.noise(s * 0.6, f * 0.007) - 0.5) * 2;
        p.line(x + j, y1 + 1, x - j, y2 - 1);
      }

      // ── the curves: barely there ──────────────────
      p.stroke(155, 148, 142, 50);
      p.strokeWeight(0.8);
      p.point(x, y1);
      p.point(x, y2);
    }
  }

  function ease(t) { return t * t * (3 - 2 * t); }

  function dayNumber() {
    const d = new Date();
    return Math.floor((d - new Date(2026, 0, 1)) / 86400000);
  }
}