briwa.dev

rain

It's raining where I am right now. This is an attempt to figure out how to run random states per "turn", in a form of raindrop ripples. Each turn draws a batch of a random number of ripples then the next one is queued to draw the next batch.

const {
  Scene,
  arc,
  tween,
  wait,
  parallel,
  sequence,
  lerp,
  easeOutLog,
  easeOutSine,
  linear,
  random,
  randomInt,
  grow,
  cue,
} = Canvas;

function dot() {
  const r = random(30, 70);
  const x = random(0, width);
  const y = random(0, height);
  const strength = random(0.4, 1);
  const count = randomInt(2,4);

  return Array.from({ length: count }, (_, i) => {
    const t = 1 - i / (count - 1);
    const ri = lerp(r * 0.2, r, easeOutLog(t));

    return arc({
      x0: x - ri,
      x1: x + ri,
      y0: y - ri,
      y1: y + ri,
      alpha: 0,
      ring: i,
      strength,
      color: { r: 224, g: 122, b: 95 },
    });
  });
}

const scene = new Scene({ canvas });

function rain() {
  const dots = Array.from({ length: randomInt(6, 10) }, dot);
  const rippleOpts = { duration: 1200, stagger: random(1200, 2400) };

  scene.spawn(
    dots,
    parallel(
      grow({ ...rippleOpts, ease: easeOutSine }),
      tween(
        { alpha: 0, lineWidth: 0.5 },
        {
          ...rippleOpts,
          ease: linear,
          from: (d) => ({
            alpha: (0.8 - d.ring * 0.25) * d.strength,
            lineWidth: (2 - d.ring * 0.6) * d.strength + 0.5,
          }),
        },
      ),
      sequence(
        wait(random(1200, 2400)),
        cue(rain),
      ),
    ),
  );
}

rain();
scene.seek(600);
loop((t) => scene.render(t));

@briwa.dev/canvas@1.6.6
← Home