260102
const { animate } = anime;
const w = 800;
const h = 800;
const SIZE = 50;
const GAP = 6;
const GRIDNUM = 3;
const ANIMATION_SPEED = 180;
const DELAY_STEP = 0.09;
const SCALE_FACTOR = 0.05;
const MIN_SCALE = 0.2;
let palette = [];
let gridSystems = [];
class GridSystem {
constructor(offsetX = 0, offsetY = 0, offsetZ = 0, colorOffset = 0) {
this.offsetX = offsetX;
this.offsetY = offsetY;
this.offsetZ = offsetZ;
this.colorOffset = colorOffset;
this.rectArray = [];
this.rectCurrentOffsets = [];
this.bgCurrentOffsets = [];
this.targetOffsetX = 0;
this.targetOffsetY = 0;
this.targetOffsetZ = 0;
this.lastTimeSlot = -1;
this.rectAnimeValue = { count: 0 };
this.bgAnimeValue = { count: 0 };
this.init();
}
init() {
let rectCenterOffset = (SIZE - GAP) / 2;
let offsetX = -(SIZE + GAP) - rectCenterOffset;
let offsetY = -(SIZE + GAP) - (SIZE - GAP) - rectCenterOffset;
for (let y = 0; y < GRIDNUM; y++) {
for (let x = 0; x < GRIDNUM; x++) {
this.rectArray.push(
createVector(
offsetX + x * (SIZE + GAP),
offsetY + y * (SIZE + GAP),
0
)
);
}
}
let gridOffset = this.getGridOffset();
this.targetOffsetX = gridOffset;
this.targetOffsetY = gridOffset;
this.targetOffsetZ = gridOffset;
for (let i = 0; i < this.rectArray.length; i++) {
this.rectCurrentOffsets.push({
x: gridOffset,
y: gridOffset,
z: gridOffset,
});
this.bgCurrentOffsets.push({
x: gridOffset,
y: gridOffset,
z: gridOffset,
});
}
animate(this.rectAnimeValue, {
count: 1,
duration: 2000,
ease: "inBounce",
loop: true,
loopDelay: 1000,
alternate: false,
});
animate(this.bgAnimeValue, {
count: 1,
duration: 2000,
ease: "inOutExpo",
loop: true,
loopDelay: 1000,
alternate: false,
});
}
getGridOffset() {
let smallGridSize = GRIDNUM * SIZE + (GRIDNUM - 1) * GAP;
let gridSpacing = smallGridSize + GAP * 4;
return (-(GRIDNUM - 1) * gridSpacing) / 2;
}
getBigGridSpacing() {
let smallGridSize = GRIDNUM * SIZE + (GRIDNUM - 1) * GAP;
return smallGridSize + GAP * 4;
}
updateTarget() {
let timeSlot = floor(frameCount / ANIMATION_SPEED);
if (timeSlot !== this.lastTimeSlot) {
let randomIndex = floor(random(GRIDNUM * GRIDNUM * GRIDNUM));
let bigGridX = randomIndex % GRIDNUM;
let bigGridY = floor((randomIndex / GRIDNUM) % GRIDNUM);
let bigGridZ = floor(randomIndex / (GRIDNUM * GRIDNUM));
let gridSpacing = this.getBigGridSpacing();
let gridOffset = this.getGridOffset();
this.targetOffsetX = gridOffset + bigGridX * gridSpacing;
this.targetOffsetY = gridOffset + bigGridY * gridSpacing;
this.targetOffsetZ = gridOffset + bigGridZ * gridSpacing;
this.lastTimeSlot = timeSlot;
}
}
calculateSize(prevX, prevY, prevZ, currentX, currentY, currentZ, baseSize) {
let moveX = currentX - prevX;
let moveY = currentY - prevY;
let moveZ = currentZ - prevZ;
let moveSpeed = sqrt(moveX * moveX + moveY * moveY + moveZ * moveZ);
let moveDirX = moveSpeed > 0 ? moveX / moveSpeed : 0;
let moveDirY = moveSpeed > 0 ? moveY / moveSpeed : 0;
let moveDirZ = moveSpeed > 0 ? moveZ / moveSpeed : 0;
let scaleFactor = 1.0 + moveSpeed * SCALE_FACTOR;
let widthRatio =
1.0 -
abs(moveDirX) * (scaleFactor - 1.0) +
(abs(moveDirY) + abs(moveDirZ)) * (scaleFactor - 1.0);
let heightRatio =
1.0 -
abs(moveDirY) * (scaleFactor - 1.0) +
(abs(moveDirX) + abs(moveDirZ)) * (scaleFactor - 1.0);
let width = baseSize * widthRatio;
let height = baseSize * heightRatio;
return {
width: max(baseSize * MIN_SCALE, width),
height: max(baseSize * MIN_SCALE, height),
};
}
drawRect(i, pos, delayedRectAnimation) {
let prevX = this.rectCurrentOffsets[i].x;
let prevY = this.rectCurrentOffsets[i].y;
let prevZ = this.rectCurrentOffsets[i].z;
this.rectCurrentOffsets[i].x = lerp(
this.rectCurrentOffsets[i].x,
this.targetOffsetX,
delayedRectAnimation
);
this.rectCurrentOffsets[i].y = lerp(
this.rectCurrentOffsets[i].y,
this.targetOffsetY,
delayedRectAnimation
);
this.rectCurrentOffsets[i].z = lerp(
this.rectCurrentOffsets[i].z,
this.targetOffsetZ,
delayedRectAnimation
);
let baseSize = SIZE - GAP;
let size = this.calculateSize(
prevX,
prevY,
prevZ,
this.rectCurrentOffsets[i].x,
this.rectCurrentOffsets[i].y,
this.rectCurrentOffsets[i].z,
baseSize
);
push();
translate(pos.x + this.offsetX, pos.y + this.offsetY, pos.z + this.offsetZ);
translate(
this.rectCurrentOffsets[i].x,
this.rectCurrentOffsets[i].y,
this.rectCurrentOffsets[i].z
);
let colorIndex = (this.colorOffset + i) % palette.length;
fill(palette[colorIndex % 4]);
let rectX = -(size.width - baseSize) / 2;
let rectY = SIZE - GAP - (size.height - baseSize) / 2;
rect(rectX, rectY, size.width, size.height);
pop();
}
drawBackground(i, pos) {
push();
translate(pos.x + this.offsetX, pos.y + this.offsetY, pos.z + this.offsetZ);
push();
noFill();
stroke(palette[5]);
translate(
this.bgCurrentOffsets[i].x,
this.bgCurrentOffsets[i].y,
this.bgCurrentOffsets[i].z
);
rect(-5, SIZE - GAP - 5, SIZE - GAP + 10, SIZE - GAP + 10);
pop();
pop();
}
update() {
this.updateTarget();
}
draw() {
push();
for (let i = 0; i < this.rectArray.length; i++) {
let pos = this.rectArray[i];
let delay = i * DELAY_STEP;
let delayedRectAnimation = max(
0,
min(1, this.rectAnimeValue.count - delay)
);
let delayedBgAnimation = max(0, min(1, this.bgAnimeValue.count - delay));
this.bgCurrentOffsets[i].x = lerp(
this.bgCurrentOffsets[i].x,
this.targetOffsetX,
delayedBgAnimation
);
this.bgCurrentOffsets[i].y = lerp(
this.bgCurrentOffsets[i].y,
this.targetOffsetY,
delayedBgAnimation
);
this.bgCurrentOffsets[i].z = lerp(
this.bgCurrentOffsets[i].z,
this.targetOffsetZ,
delayedBgAnimation
);
this.drawBackground(i, pos);
this.drawRect(i, pos, delayedRectAnimation);
}
pop();
}
}
function setup() {
createCanvas(w, h, WEBGL);
palette = colorArray[1].colors;
background(palette[4]);
stroke(palette[6]);
strokeWeight(4);
gridSystems.push(new GridSystem(0, 0, 0, 0));
gridSystems.push(new GridSystem(0, 0, 0, 2));
gridSystems.push(new GridSystem(0, 0, 0, 4));
}
function draw() {
orbitControl();
background(palette[4]);
for (let gridSystem of gridSystems) {
gridSystem.update();
gridSystem.draw();
}
}
const colorArray = [
{
id: 0,
colors: ["#253276", "#dfdad3", "#ffffff", "#000000"],
},
{
id: 1,
colors: [
"#9dbdba",
"#f8b042",
"#e47763",
"#253276",
"#dfdad3",
"#ffffff",
"#000000",
],
},
]; const { animate } = anime;
const w = 800;
const h = 800;
const SIZE = 50;
const GAP = 6;
const GRIDNUM = 3;
const ANIMATION_SPEED = 180;
const DELAY_STEP = 0.09;
const SCALE_FACTOR = 0.05;
const MIN_SCALE = 0.2;
let palette = [];
let gridSystems = [];
class GridSystem {
constructor(offsetX = 0, offsetY = 0, offsetZ = 0, colorOffset = 0) {
this.offsetX = offsetX;
this.offsetY = offsetY;
this.offsetZ = offsetZ;
this.colorOffset = colorOffset;
this.rectArray = [];
this.rectCurrentOffsets = [];
this.bgCurrentOffsets = [];
this.targetOffsetX = 0;
this.targetOffsetY = 0;
this.targetOffsetZ = 0;
this.lastTimeSlot = -1;
this.rectAnimeValue = { count: 0 };
this.bgAnimeValue = { count: 0 };
this.init();
}
init() {
let rectCenterOffset = (SIZE - GAP) / 2;
let offsetX = -(SIZE + GAP) - rectCenterOffset;
let offsetY = -(SIZE + GAP) - (SIZE - GAP) - rectCenterOffset;
for (let y = 0; y < GRIDNUM; y++) {
for (let x = 0; x < GRIDNUM; x++) {
this.rectArray.push(
createVector(
offsetX + x * (SIZE + GAP),
offsetY + y * (SIZE + GAP),
0
)
);
}
}
let gridOffset = this.getGridOffset();
this.targetOffsetX = gridOffset;
this.targetOffsetY = gridOffset;
this.targetOffsetZ = gridOffset;
for (let i = 0; i < this.rectArray.length; i++) {
this.rectCurrentOffsets.push({
x: gridOffset,
y: gridOffset,
z: gridOffset,
});
this.bgCurrentOffsets.push({
x: gridOffset,
y: gridOffset,
z: gridOffset,
});
}
animate(this.rectAnimeValue, {
count: 1,
duration: 2000,
ease: "inBounce",
loop: true,
loopDelay: 1000,
alternate: false,
});
animate(this.bgAnimeValue, {
count: 1,
duration: 2000,
ease: "inOutExpo",
loop: true,
loopDelay: 1000,
alternate: false,
});
}
getGridOffset() {
let smallGridSize = GRIDNUM * SIZE + (GRIDNUM - 1) * GAP;
let gridSpacing = smallGridSize + GAP * 4;
return (-(GRIDNUM - 1) * gridSpacing) / 2;
}
getBigGridSpacing() {
let smallGridSize = GRIDNUM * SIZE + (GRIDNUM - 1) * GAP;
return smallGridSize + GAP * 4;
}
updateTarget() {
let timeSlot = floor(frameCount / ANIMATION_SPEED);
if (timeSlot !== this.lastTimeSlot) {
let randomIndex = floor(random(GRIDNUM * GRIDNUM * GRIDNUM));
let bigGridX = randomIndex % GRIDNUM;
let bigGridY = floor((randomIndex / GRIDNUM) % GRIDNUM);
let bigGridZ = floor(randomIndex / (GRIDNUM * GRIDNUM));
let gridSpacing = this.getBigGridSpacing();
let gridOffset = this.getGridOffset();
this.targetOffsetX = gridOffset + bigGridX * gridSpacing;
this.targetOffsetY = gridOffset + bigGridY * gridSpacing;
this.targetOffsetZ = gridOffset + bigGridZ * gridSpacing;
this.lastTimeSlot = timeSlot;
}
}
calculateSize(prevX, prevY, prevZ, currentX, currentY, currentZ, baseSize) {
let moveX = currentX - prevX;
let moveY = currentY - prevY;
let moveZ = currentZ - prevZ;
let moveSpeed = sqrt(moveX * moveX + moveY * moveY + moveZ * moveZ);
let moveDirX = moveSpeed > 0 ? moveX / moveSpeed : 0;
let moveDirY = moveSpeed > 0 ? moveY / moveSpeed : 0;
let moveDirZ = moveSpeed > 0 ? moveZ / moveSpeed : 0;
let scaleFactor = 1.0 + moveSpeed * SCALE_FACTOR;
let widthRatio =
1.0 -
abs(moveDirX) * (scaleFactor - 1.0) +
(abs(moveDirY) + abs(moveDirZ)) * (scaleFactor - 1.0);
let heightRatio =
1.0 -
abs(moveDirY) * (scaleFactor - 1.0) +
(abs(moveDirX) + abs(moveDirZ)) * (scaleFactor - 1.0);
let width = baseSize * widthRatio;
let height = baseSize * heightRatio;
return {
width: max(baseSize * MIN_SCALE, width),
height: max(baseSize * MIN_SCALE, height),
};
}
drawRect(i, pos, delayedRectAnimation) {
let prevX = this.rectCurrentOffsets[i].x;
let prevY = this.rectCurrentOffsets[i].y;
let prevZ = this.rectCurrentOffsets[i].z;
this.rectCurrentOffsets[i].x = lerp(
this.rectCurrentOffsets[i].x,
this.targetOffsetX,
delayedRectAnimation
);
this.rectCurrentOffsets[i].y = lerp(
this.rectCurrentOffsets[i].y,
this.targetOffsetY,
delayedRectAnimation
);
this.rectCurrentOffsets[i].z = lerp(
this.rectCurrentOffsets[i].z,
this.targetOffsetZ,
delayedRectAnimation
);
let baseSize = SIZE - GAP;
let size = this.calculateSize(
prevX,
prevY,
prevZ,
this.rectCurrentOffsets[i].x,
this.rectCurrentOffsets[i].y,
this.rectCurrentOffsets[i].z,
baseSize
);
push();
translate(pos.x + this.offsetX, pos.y + this.offsetY, pos.z + this.offsetZ);
translate(
this.rectCurrentOffsets[i].x,
this.rectCurrentOffsets[i].y,
this.rectCurrentOffsets[i].z
);
let colorIndex = (this.colorOffset + i) % palette.length;
fill(palette[colorIndex % 4]);
let rectX = -(size.width - baseSize) / 2;
let rectY = SIZE - GAP - (size.height - baseSize) / 2;
rect(rectX, rectY, size.width, size.height);
pop();
}
drawBackground(i, pos) {
push();
translate(pos.x + this.offsetX, pos.y + this.offsetY, pos.z + this.offsetZ);
push();
noFill();
stroke(palette[5]);
translate(
this.bgCurrentOffsets[i].x,
this.bgCurrentOffsets[i].y,
this.bgCurrentOffsets[i].z
);
rect(-5, SIZE - GAP - 5, SIZE - GAP + 10, SIZE - GAP + 10);
pop();
pop();
}
update() {
this.updateTarget();
}
draw() {
push();
for (let i = 0; i < this.rectArray.length; i++) {
let pos = this.rectArray[i];
let delay = i * DELAY_STEP;
let delayedRectAnimation = max(
0,
min(1, this.rectAnimeValue.count - delay)
);
let delayedBgAnimation = max(0, min(1, this.bgAnimeValue.count - delay));
this.bgCurrentOffsets[i].x = lerp(
this.bgCurrentOffsets[i].x,
this.targetOffsetX,
delayedBgAnimation
);
this.bgCurrentOffsets[i].y = lerp(
this.bgCurrentOffsets[i].y,
this.targetOffsetY,
delayedBgAnimation
);
this.bgCurrentOffsets[i].z = lerp(
this.bgCurrentOffsets[i].z,
this.targetOffsetZ,
delayedBgAnimation
);
this.drawBackground(i, pos);
this.drawRect(i, pos, delayedRectAnimation);
}
pop();
}
}
function setup() {
createCanvas(w, h, WEBGL);
palette = colorArray[1].colors;
background(palette[4]);
stroke(palette[6]);
strokeWeight(4);
gridSystems.push(new GridSystem(0, 0, 0, 0));
gridSystems.push(new GridSystem(0, 0, 0, 2));
gridSystems.push(new GridSystem(0, 0, 0, 4));
}
function draw() {
orbitControl();
background(palette[4]);
for (let gridSystem of gridSystems) {
gridSystem.update();
gridSystem.draw();
}
}
const colorArray = [
{
id: 0,
colors: ["#253276", "#dfdad3", "#ffffff", "#000000"],
},
{
id: 1,
colors: [
"#9dbdba",
"#f8b042",
"#e47763",
"#253276",
"#dfdad3",
"#ffffff",
"#000000",
],
},
];