<script src="https://cdn.jsdelivr.net/npm/p5@1.4.1/lib/p5.min.js"></script>
<!-- p5.js より後に追加する -->
<!--
<script src="https://cdn.jsdelivr.net/npm/p5.capture@1.1.0/dist/p5.capture.umd.min.js"></script>
-->
/* 録画用
P5Capture.setDefaultOptions({
  format: "gif",
  framerate: 30,
  quality: 0.8,
  width: 320,
});
/*

/**
 * @param A 振幅
 * @param b 減衰定数
 * @param m 質量
 * @param k ばね定数
 * @param p 初期位相
 * @return function
 */
const F = (A, b, m, k, p) => (A, t) => {
  // @param w_ 減衰振動子の角振動定数
  const w_ = sqrt(k / m - b ** 2 / (4 * m ** 2));
  return A * exp((-b * t) / (2 * m)) * cos(w_ * t - p);
};

// X(A, t) ... 振幅A, 時間tを引数にとる座標
const X = F(100, 1e2, 1e5, 1e2, 0);

// const W = 600;
// const H = 600;
let W, H;

// translate()基準のマウス座標
let mX;
let mY;

// mouseClickedが発火した時のマウス座標や時間
let mXs = 0;
let mYs = 0;
let clickedT = 0;

function setup() {
  createCanvas((W = windowWidth), (H = windowHeight));
  strokeWeight(10);
}

function draw() {
  /* 録画用
  if (frameCount === 1) {
    const capture = P5Capture.getInstance();
    capture.start();
  }
  */
  background(220);
  translate(0, H / 2);

  push();
  {
    stroke(200);
    strokeWeight(1);
    line(-W, 0, W, 0);
    line(0, -H, 0, H);
  }
  pop();

  push();
  {
    strokeWeight(5);
    point(mXs, mYs);
    strokeWeight(1);
    line(-W, mYs, W, mYs);
  }
  pop();
  mX = mouseX;
  mY = mouseY - H / 2;

  let t = (frameCount - clickedT) * 4;

  push();
  {
    stroke(200);
    strokeWeight(1);
    line(-mX, 0, mX, 0);
    line(0, -mY, 0, mY);
  }
  pop();

  text(
    `mX, mY = ${mX}, ${mY}\nmXs, mY = ${mXs}, ${mYs}\nt = ${t}`,
    20,
    20 - H / 2,
    W,
    H
  );

  for (let i = 0, N = 100; i <= N; i++) {
    push();
    stroke(0 + (i / N) * 220);
    point((t - i) % W, X(mYs, t - i));
    pop();
  }
}

function mouseClicked() {
  mXs = mX;
  mYs = mY;
  clickedT = frameCount;
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.