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);
- 立体感が損なわれている感じがする