Chapter 97

時間

miku
miku
2021.11.20に更新

この章では時間に関する実装について扱う。

早回し

function draw() {
  for (let i = 0; i < 20; i++) {
  }
}

ジェネレーティブアートのような描画の重ね合わせを行う場合、draw() の実行間隔では描画の反映が遅いと感じる場合がある。その場合 x++x += 2 のように書き直してしまうと早回しではなくスキップしてしまうので、ループ文で1フレームあたりの実行回数を増やすなどの対処方法がある。

function draw() {
  if (frameCount % 100 === 0) {
  }
}

逆に更新が速すぎる場合は frameCount のようなカウンタを利用して、n で割った余りが 0 なら n フレームおきの実行になる。

円運動による時間の利用

const r = 100;
const speed = 80;

function setup() {
  createCanvas(windowWidth, windowHeight);
}

function draw() {
  clear();
  translate(width / 2, height / 2);

  const x = cos(frameCount / speed) * r;
  const y = sin(frameCount / speed) * r;
  circle(x, y, 10);
}

cossin に経過時間の値、たとえば frameCount などに依存した値を指定して座標を作ると円運動になる。

アナログ時計の実装

const r = 100;

function setup() {
  createCanvas(windowWidth, windowHeight);
  angleMode(DEGREES);
}

function draw() {
  const date = new Date();

  clear();

  // 秒針
  strokeWeight(2);
  stroke("#de980f");
  noFill();
  translate(width / 2, height / 2);
  rotate(map(date.getSeconds(), 0, 60, -90, 270));
  line(0, 0, r * 0.95, 0);
  resetMatrix();

  // 分針
  strokeWeight(4);
  stroke("#1c8B94");
  noFill();
  translate(width / 2, height / 2);
  rotate(map(date.getMinutes(), 0, 60, -90, 270));
  line(0, 0, r * 0.9, 0);
  resetMatrix();

  // 時針
  strokeWeight(4);
  stroke("#cd3830");
  noFill();
  translate(width / 2, height / 2);
  rotate(map((date.getHours() % 12) + date.getMinutes() / 60, 0, 12, -90, 270));
  line(0, 0, r / 2, 0);
  resetMatrix();

  // 外枠の円
  strokeWeight(4);
  stroke("#ccc");
  noFill();
  circle(width / 2, height / 2, r * 2);

  // 中央の留め金円
  noStroke();
  fill("#ccc");
  circle(width / 2, height / 2, 10);
}

アナログ時計の作例。

現在時刻を得るには new Date() でDateオブジェクトを作成して、そこから時/分/秒を取り出すには getHours(), getMinutes(), getSeconds() を実行する。

あとはそれぞれの値に応じた針の角度を取得して座標を回転させ、0°の方向に棒を描画すればいい。

rotate(map(date.getSeconds(), 0, 60, -90, 270));
line(0, 0, r * 0.95, 0);

上記は秒針の実装になる。秒がとり得る範囲を秒針の角度に変換したい。0秒のとき12時の方向である-90°になり、そこから時間が経つに連れ角度が増えていき、60秒のときに一周して270°になるので map(date.getMinutes(), 0, 60, -90, 270) を角度にすればいい。

rotate(map(date.getMinutes(), 0, 60, -90, 270));
line(0, 0, r * 0.9, 0);

次に分針の実装だが、分がとり得る範囲は秒と同じなので先程と同様の指定方法になる。

rotate(map((date.getHours() % 12) + date.getMinutes() / 60, 0, 12, -90, 270));
line(0, 0, r / 2, 0);

最後に時針の実装になる。getHours() は0~23を返すがアナログ時計の1周は 12 なので 12 で割った余りを現在の時にする。それに加えて、たとえば6時半の場合の時針の位置は6時と7時の間になるように、時針は分の影響も受けるので、現在の分を 60 で割ったものを現在の時に加える。あとは map() を利用して現在の時を0~12の範囲から-90~270の範囲に変換したものを角度にすればいい。