codepens/practice-canvas2d/dist/script.js

345 lines
7.3 KiB
JavaScript

import {Ease} from 'https://assets.codepen.io/3919397/ease.js';
import {Utils} from 'https://assets.codepen.io/3919397/utilities.js';
let gui, canvas, c, width, height, frameSize, id, ease, shapes, size, scale, num, maxDist, hexPoints;
const setupGui = () => {
gui = new dat.GUI();
gui.params = {
timeScale: 0.0005,
ease: 'easeInOutQuart',
number: 1,
scale: 150,
frame: false,
start: () => start(),
stop: () => stop()
};
gui.ctrls = {
timeScale: gui.add(gui.params, 'timeScale', 0.0001, 0.005, 0.0001),
ease: gui.add(gui.params, 'ease', Ease.returnEaseType())
.onChange(() => initialize()),
number: gui.add(gui.params, 'number', 1, 30, 1)
.onChange(() => initialize()),
scale: gui.add(gui.params, 'scale', 1, 500, 1)
.onChange(() => initialize()),
frame: gui.add(gui.params, 'frame', false),
start: gui.add(gui.params, 'start'),
stop: gui.add(gui.params, 'stop')
};
gui.close();
};
const addFrame = () => {
c.rect(
width / 2 - frameSize / 2,
height / 2 - frameSize / 2,
frameSize,
frameSize
);
c.clip();
};
const setupCanvas = () => {
canvas = document.createElement('canvas');
document.getElementsByTagName('body')[0].appendChild(canvas);
c = canvas.getContext('2d');
};
const initialize = () => {
if (id) {
cancelAnimationFrame(id);
}
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
ease = Ease.returnEaseFunc(gui.params.ease);
shapes = new Array();
scale = gui.params.scale;
num = gui.params.number;
frameSize = Math.min(width * 0.9, height * 0.9);
maxDist = 0;
hexPoints = getPolygonPoints(360, 4);
shapes = getSquareGrid(num);
draw(0);
};
const getSquareGrid = (num) => {
const vectors = new Array();
for (let x = -num; x <= num; x++) {
for (let y = -num; y <= num; y++) {
vectors.push([x, y]);
}
}
const tmp = new Array();
for (let i = 0; i < vectors.length; i++) {
const params = {};
const x = vectors[i][0] * scale;
const y = vectors[i][1] * scale;
const d = Math.sqrt(x * x + y * y);
params.x = x;
params.y = y;
params.d = d;
params.i = i;
maxDist = Math.max(d, maxDist);
tmp.push(params);
}
size = Math.floor(scale * Math.sqrt(2) / 2);
//size = scale / 2;
return tmp;
};
const getHexGrid = (num) => {
const vectors = new Array();
for (let x = -num; x <= num; x++) {
for (let y = -num; y <= num; y++) {
for (let z = -num; z <= num; z++) {
if (x + y + z === 0) {
vectors.push([x, y]);
}
}
}
}
const tmp = new Array();
for (let i = 0; i < vectors.length; i++) {
const params = {};
const x = Math.sqrt(3) * (vectors[i][0] + vectors[i][1] / 2) / 2 * scale;
const y = 3 / 2 * vectors[i][1] / 2 * scale;
const d = Math.sqrt(x * x + y * y);
params.x = x;
params.y = y;
params.d = d;
maxDist = Math.max(d, maxDist);
tmp.push(params);
}
size = Math.sqrt(3) * (scale / 2) / 2;
return tmp;
};
const getSquareGrid2 = (num) => {
const tmp = new Array();
const ajust = num * scale / 2 - scale / 2;
for (let y = 0; y < num; y++) {
for (let x = 0; x < num; x++) {
const params = {};
const i = y * num + x;
let ny = scale * y - ajust;
let nx = scale * x - ajust;
if (y % 2 === 0) {
nx += scale / 2;
}
const d = Math.sqrt(nx * nx + ny * ny);
params.x = nx;
params.y = ny;
params.d = d;
params.i = i;
params.col = x;
params.row = y;
maxDist = Math.max(dist, maxDist);
tmp.push(params);
}
}
size = scale / 2;
return tmp;
};
const getCircleGrid = (num) => {
const tmp = new Array();
for (let k = 1; k <= num; k++) {
for (let j = 0; j < k * num; j++) {
const params = {};
const i = k * k * num + j;
const x = Math.cos(Math.PI * 2 / (num * k) * j) * k * scale * 0.4;
const y = Math.sin(Math.PI * 2 / (num * k) * j) * k * scale * 0.4;
const d = Math.sqrt(x * x + y * y);
params.x = x;
params.y = y;
params.d = d;
params.i = i;
maxDist = Math.max(d, maxDist);
tmp.push(params);
}
}
size = Math.floor(scale * 0.4 * 2 * Math.PI / num / 2);
return tmp;
};
const getPolygonPoints = (number, poly) => {
const tmp = new Array();
for (let j = 0; j < poly; j++) {
for (let i = 0; i < number / poly; i++) {
const x = Math.cos(j / poly * Math.PI * 2);
const y = Math.sin(j / poly * Math.PI * 2);
let nx, ny;
if (j === poly - 1) {
nx = Math.cos(0);
ny = Math.sin(0);
} else {
nx = Math.cos((j + 1) / poly * Math.PI * 2);
ny = Math.sin((j + 1) / poly * Math.PI * 2);
}
const sx = x + (nx - x) * (i / (number / poly));
const sy = y + (ny - y) * (i / (number / poly));
tmp.push([sx, sy]);
}
}
return tmp;
};
const getNewPoints = (t) => {
const tmp = new Array();
for (let i = 0; i < number; i++) {
let x, y;
tmp.push([x, y]);
}
return tmp;
};
const drawPolygon = (x, y, num, size, fillStyle, strokeStyle) => {
c.save();
c.fillStyle = fillStyle;
c.strokeStyle = strokeStyle;
c.beginPath();
for (let i = 0; i < num; i++) {
const nx = Math.cos(i / num * Math.PI * 2) * size + x;
const ny = Math.sin(i / num * Math.PI * 2) * size + y;
if (i === 0) {
c.moveTo(nx, ny);
} else {
c.lineTo(nx, ny);
}
}
c.closePath();
//c.fill();
c.stroke();
c.restore();
};
const draw = (t) => {
t *= gui.params.timeScale;
c.save();
c.fillStyle = 'rgba(0, 0, 0, 0.03)';
c.fillRect(0, 0, width, height);
//c.clearRect(0, 0, width, height);
if (gui.params.frame) addFrame();
c.translate(width / 2, height / 2);
c.lineCap = 'round';
c.lineWidth = 30;
for (let i = 0; i < shapes.length; i++) {
let scaledT = (t - (shapes[i].d / maxDist)) % 1;
scaledT = ease(Math.abs(scaledT));
const x = shapes[i].x;
const y = shapes[i].y;
c.save();
c.translate(x, y);
c.rotate(Math.PI / 2);
c.translate(-x, -y);
let index = Math.floor(Utils.map(scaledT, 0, 1, 0, hexPoints.length - 1));
let endex = Math.ceil(Utils.map(scaledT, 0, 1, index + 1, hexPoints.length - 1));
c.strokeStyle = `hsl(${360 * scaledT}, 80%, 60%)`;
c.translate(x, y);
c.beginPath();
c.moveTo(hexPoints[index][0] * size, hexPoints[index][1] * size);
for (let i = index; i < endex; i++) {
if (endex === hexPoints.length - 1) {
c.lineTo(hexPoints[0][0] * size, hexPoints[0][1] * size);
} else {
c.lineTo(hexPoints[i][0] * size, hexPoints[i][1] * size);
}
}
c.stroke();
c.restore();
}
c.restore();
id = requestAnimationFrame(draw);
};
const start = () => {
initialize();
};
const stop = () => {
if (id) {
cancelAnimationFrame(id);
id = null;
}
};
(() => {
window.addEventListener('DOMContentLoaded', () => {
console.clear();
setupGui();
setupCanvas();
initialize();
});
window.addEventListener('resize', () => {
initialize();
});
})();