251115

const { animate } = anime;
const W = 800;
const H = 800;
const SPACE = 400;
const RECTNUM = 5;
const SIZE = 200;
const TIME = 1500;
const DELAY = 200;

let palette = [];
let points = [];
let prevPoints = [];
let pointsRefreshed = true;
let animeValue = {
  count: 0,
};

function setup() {
  setAttributes("depth", false);
  createCanvas(W, H, WEBGL);
  palette = colorArray[2].colors;
  background(palette[4]);
  frameRate(60);
  // noStroke();
  noFill();
  stroke(palette[0]);
  strokeWeight(2);
  animate(animeValue, {
    count: 1,
    duration: TIME,
    ease: "outExpo",
    loop: true,
    loopDelay: DELAY,
  });
  getPoints();
}

function draw() {
  orbitControl();
  background(palette[4]);

  let f = animeValue.count;
  if (f <= 0.1) {
    if (!pointsRefreshed) {
      // 前のpointsをコピー
      prevPoints = [];
      for (let i = 0; i < points.length; i++) {
        prevPoints.push({
          x: points[i].x,
          y: points[i].y,
          z: points[i].z,
          w: points[i].w,
          h: points[i].h,
          o: points[i].o,
        });
      }
      points = [];
      getPoints();
      pointsRefreshed = true;
    }
  } else {
    pointsRefreshed = false;
  }

  let visPoints = [];
  if (prevPoints.length === points.length) {
    for (let i = 0; i < points.length; i++) {
      let a = prevPoints[i];
      let b = points[i];
      visPoints.push({
        x: lerp(a.x, b.x, f),
        y: lerp(a.y, b.y, f),
        z: lerp(a.z, b.z, f),
        w: lerp(a.w, b.w, f),
        h: lerp(a.h, b.h, f),
        o: lerp(a.o, b.o, f),
      });
    }
  } else {
    visPoints = points;
  }

  //右下に偏るので戻す
  translate(-SIZE / 2, -SIZE / 2, 0);
  drawRectsAndLines(visPoints);
}

function getPoints() {
  for (let i = 0; i < RECTNUM; i++) {
    let vect = {
      x: random(-SPACE / 2, SPACE / 2),
      y: random(-SPACE / 2, SPACE / 2),
      z: random(-SPACE / 2, SPACE / 2),
      w: random(SIZE / 2, SIZE),
      h: random(SIZE / 2, SIZE),
      o: random(0, 1),
    };
    points.push(vect);
  }
}

function drawRectsAndLines(pts) {
  for (let i = 0; i < pts.length; i++) {
    push();
    let currIndex = i;
    let prevIndex = (i - 1 + pts.length) % pts.length;
    let curr = pts[i];
    let prev = pts[prevIndex];

    let theta = animeValue.count * TAU;

    let rotatedVerts = getRotatedVerts(curr, theta, currIndex);
    let rotatedPrevVerts = getRotatedVerts(prev, theta, prevIndex);
    // 奇数のときだけ最後にズレを直す
    if (RECTNUM % 2 && i === 0) {
      rotatedPrevVerts[2].x = rotatedPrevVerts[0].x;
      rotatedPrevVerts[3].x = rotatedPrevVerts[1].x;
      rotatedPrevVerts[2].y = rotatedPrevVerts[0].y;
      rotatedPrevVerts[3].y = rotatedPrevVerts[1].y;
      rotatedPrevVerts[2].z = rotatedPrevVerts[0].z;
      rotatedPrevVerts[3].z = rotatedPrevVerts[1].z;
    }

    if (i % 2) {
      line(
        rotatedVerts[0].x,
        rotatedVerts[0].y,
        rotatedVerts[0].z,
        rotatedPrevVerts[0].x,
        rotatedPrevVerts[0].y,
        rotatedPrevVerts[0].z
      );
      line(
        rotatedVerts[1].x,
        rotatedVerts[1].y,
        rotatedVerts[1].z,
        rotatedPrevVerts[1].x,
        rotatedPrevVerts[1].y,
        rotatedPrevVerts[1].z
      );
    } else {
      line(
        rotatedVerts[2].x,
        rotatedVerts[2].y,
        rotatedVerts[2].z,
        rotatedPrevVerts[2].x,
        rotatedPrevVerts[2].y,
        rotatedPrevVerts[2].z
      );
      line(
        rotatedVerts[3].x,
        rotatedVerts[3].y,
        rotatedVerts[3].z,
        rotatedPrevVerts[3].x,
        rotatedPrevVerts[3].y,
        rotatedPrevVerts[3].z
      );
    }

    let c = color(palette[0]);
    c.setAlpha(100);
    fill(c);

    beginShape();
    for (let j = 0; j < rotatedVerts.length; j++) {
      vertex(rotatedVerts[j].x, rotatedVerts[j].y, rotatedVerts[j].z);
    }
    endShape(CLOSE);
    pop();
  }
}

function getRotatedVerts(obj, theta, index) {
  // 中心座標
  let cx = obj.x + obj.w / 2;
  let cy = obj.y + obj.h / 2;
  let cz = obj.z;
  // 四角の各頂点
  let verts = [
    { x: -obj.w / 2, y: -obj.h / 2, z: 0 },
    { x: obj.w / 2, y: -obj.h / 2, z: 0 },
    { x: obj.w / 2, y: obj.h / 2, z: 0 },
    { x: -obj.w / 2, y: obj.h / 2, z: 0 },
  ];
  // 四角ごと & 頂点ごとに回転角を少しずつずらす
  return verts.map((v, j) => {
    let offset = theta + j * obj.o + index * 0.8;
    let px = cx + v.x;
    let py = cy + v.y;
    let pz = cz + v.z;
    // 現在値と差分を取る
    let dy = py - cy;
    let dz = pz - cz;
    // 行列計算(YZ回転)
    let ry = dy * cos(offset) - dz * sin(offset);
    let rz = dy * sin(offset) + dz * cos(offset);
    return {
      x: px,
      y: cy + ry,
      z: cz + rz,
    };
  });
}

const colorArray = [
  {
    id: 0,
    colors: ["#253276", "#dfdad3", "#ffffff", "#000000"],
  },
  {
    id: 1,
    colors: ["#2E5400", "#dfdad3", "#ffffff", "#000000"],
  },
  {
    id: 2,
    colors: ["#253276", "#f9d3cc", "#f07433", "#437800", "#dfdad3"],
  },
];
  • 深度テストは、
setAttributes("depth", false);

で解除できる

  • 回転行列
let ry = dy * cos(offset) - dz * sin(offset);
let rz = dy * sin(offset) + dz * cos(offset);
  • 立体感が損なわれている感じがする

Last Update :