Chapter 50

ループ

miku
miku
2021.11.15に更新

線形補間の関数である lerp(a, b, t) で、a~b の間の割合 t の位置を計算するが、この t の値を増やし続け、1 になったらまた 0 に戻すと a~b の間を位置を延々と計算することになる。この章ではその事象を利用したアニメーションを作ることを扱う。

ループ

let a, b, t;

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

  a = { x: width / 4, y: height / 4 };
  b = { x: (width / 4) * 3, y: (height / 4) * 3 };
  t = 0;
}

function draw() {
  t += 0.002;
  t %= 1;

  clear();

  stroke(240);
  noFill();
  line(a.x, a.y, b.x, b.y);

  stroke(240);
  fill("#292a33");
  const x = lerp(a.x, b.x, t);
  const y = lerp(a.y, b.y, t);
  circle(x, y, 15);
}

線形補間に利用する t の値を増やし続け、t %= 1 で範囲を 0~1 に制限する。その t で計算した位置に円を配置すると、始点と終点の間を延々と円がループすることになる。

ループ その2

let points, t;

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

  points = [
    { x: width / 3, y: height / 3 },
    { x: width / 3, y: (height / 3) * 2 },
    { x: (width / 3) * 2, y: (height / 3) * 2 },
    { x: (width / 3) * 2, y: height / 3 },
  ];

  t = 0;
}

function draw() {
  t += 0.01;
  t %= 1;

  clear();
  for (let i = 0; i < points.length; i++) {
    const prev = points[i];
    const next = points[(i + 1) % points.length];

    stroke(240);
    noFill();
    line(prev.x, prev.y, next.x, next.y);
  }

  for (let i = 0; i < points.length; i++) {
    const prev = points[i];
    const next = points[(i + 1) % points.length];
    const x = lerp(prev.x, next.x, t);
    const y = lerp(prev.y, next.y, t);

    stroke(240);
    fill("#292a33");
    circle(x, y, 15);
  }
}

先程の作例を繋げて矩形型にした作例。ある線の終点が別の線の始点に繋がっているので、円が矩形の線上を渡り歩いているように見える。

ループ その3

const n = 10;
const r = 100;
let points, t;

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

  points = [];

  for (let i = 0; i < n; i++) {
    const angle = (360 / n) * i;
    const a = i % 2 == 0 ? 1 : 2;
    const x = width / 2 + (cos(angle) * r) / a;
    const y = height / 2 + (sin(angle) * r) / a;
    points.push({ x, y });
  }

  t = 0;
}

function draw() {
  t += 0.01;
  t %= 1;

  clear();

  for (let i = 0; i < points.length; i++) {
    const prev = points[i];
    const next = points[(i + 1) % points.length];

    stroke(240);
    noFill();
    line(prev.x, prev.y, next.x, next.y);
  }

  for (let i = 0; i < points.length; i++) {
    const prev = points[i];
    const next = points[(i + 1) % points.length];
    const x = lerp(prev.x, next.x, t);
    const y = lerp(prev.y, next.y, t);

    stroke(240);
    fill("#292a33");
    circle(x, y, 10);
  }
}

形状を星型に変えた作例。

ループ その4

const space = 10;
let l0, l1, t;

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

  l0 = { x1: 10, y1: 10, x2: 100, y2: 100, t: 0 };
  l1 = { x1: 100, y1: height / 2, x2: width - 100, y2: height / 2, t: 0 };
  t = 0;
}

function draw() {
  clear();

  drawLine(l0);
  drawLine(l1);
}

function drawLine(l) {
  t += 0.03;
  t %= 1;

  const x1 = l.x1;
  const y1 = l.y1;
  const x2 = l.x2;
  const y2 = l.y2;

  const d = dist(x1, y1, x2, y2);
  const n = floor(d / space);

  for (let i = 0; i < n; i++) {
    const x = lerp(x1, x2, (space * i) / d + t / n);
    const y = lerp(y1, y2, (space * i) / d + t / n);
    circle(x, y, 5);
  }

  circle(x1, y1, 14);
  circle(x2, y2, 14);
}

点線にした作例。