kleinesbuero/htdocs/kleinesbuero.js

214 lines
No EOL
5.4 KiB
JavaScript

class Wiggler {
constructor(canvas, target) {
console.log("start init")
this.canvas = canvas;
this.ctx = canvas.getContext("2d");
this.width = this.canvas.width;
this.height = this.canvas.height;
let maxx = Math.max(...target.flatMap(l => l.map(k => k[0])));
let maxy = Math.max(...target.flatMap(l => l.map(k => k[1])))
let offsx = (this.width - maxx) / 2
let offsy = (this.height - maxy) / 2
this.target = target.map(c => c.map(l => [l[0] + offsx, l[1] + offsy]));
// this.initRandom();
// this.initCorners();
this.current = this.initEdges(maxx, maxy);
}
initRandom() {
return this.target.map(l => {
const px = Math.random() * this.width;
const py = Math.random() * this.height;
const r = Math.PI * 2;
const tx = px + Math.cos(r) * 10;
const ty = py + Math.sin(r) * 10;
return [[px, py], [tx, ty]];
});
}
initCorners() {
return this.target.map(l => {
const px = Math.random() < .5 ? 0 : this.width;
const py = Math.random() < .5 ? 0 : this.height;
const r = Math.PI * 2;
const tx = px + Math.cos(r) * 10;
const ty = py + Math.sin(r) * 10;
return [[px, py], [tx, ty]];
});
}
initEdges() {
return this.target.map(() => {
var px, py;
if (Math.random() < .5) {
px = Math.random() < .5 ? 0 : this.width;
py = Math.random() * this.height;
} else {
px = Math.random() * this.width;
py = Math.random() < .5 ? 0 : this.height;
}
return [[px, py], [px, py]];
});
}
start() {
console.log("start");
if (!this.running) {
this.running = true;
this.animate();
}
}
stop() {
console.log("stop");
if (this.running) {
this.running = false;
}
}
toggle() {
this.running = !this.running;
if (this.running) {
this.animate();
} else {
console.log("stop");
}
}
animate() {
if (this.running) {
this.update();
this.draw();
window.requestAnimationFrame(() => { this.animate(); })
}
}
dist(p1, p2) {
const dx = p1[0] - p2[0];
const dy = p1[1] - p2[1];
return Math.sqrt(dx * dx + dy * dy);
}
mv(d) { return Math.random() * d - (d / 2.0); }
update() {
var changed = false;
for (var l = 0; l < this.current.length; l++) {
for (var p = 0; p < 2; p++) {
const cp = this.current[l][p];
const tp = this.target[l][p];
if (this.dist(cp, tp) > .5) {
changed = true;
const dist = this.dist(cp, tp);
var np;
var ndist;
do {
const dx = this.mv(Math.sqrt(dist) + 2);
const dy = this.mv(Math.sqrt(dist) + 2);
np = [cp[0] + dx, cp[1] + dy];
ndist = this.dist(np, tp);
} while (ndist > dist);
this.current[l][p] = np;
}
}
}
if (!changed) {
this.running = false;
}
}
draw() {
this.fillStyle = "#C9E6F0"
this.ctx.clearRect(0, 0, 800, 600)
this.ctx.strokeStyle = "white"
this.ctx.lineWidth = 3
this.ctx.lineJoin = "round"
this.ctx.lineCap = "round"
this.current.forEach(l => {
this.ctx.beginPath()
this.ctx.moveTo(l[0][0], l[0][1])
this.ctx.lineTo(l[1][0], l[1][1])
this.ctx.stroke()
});
}
mash() {
// replace target lines randomly
for (let i = 0; i < this.target.length; i++) {
let c0, c1;
do {
c0 = i
c1 = Math.floor(Math.random() * this.target.length)
} while (c0 == c1);
let l0 = this.target[c0][0]
let l1 = this.target[c0][1]
this.target[c0][0] = this.target[c1][0]
this.target[c0][1] = this.target[c1][1]
this.target[c1][0] = l0
this.target[c1][1] = l1
}
if (!this.running) {
this.running = true;
this.animate();
}
}
}
Array.__prototype
const textToCoords = (text, scale, alphabet) => {
var base = 0;
var output = Array.from(text).flatMap(c => {
const g = alphabet[c].map(l =>
l.map(p => [p[0] * scale + base, p[1] * scale])
);
const maxx = alphabet[c].map(l => Math.max(l[0][0], l[1][0]));
// width of character plus
const inc = (Math.max(1, Math.max(...maxx)) + 0.2) * scale;
base += inc;
return g;
});
return output;
};
document.addEventListener('DOMContentLoaded', () => {
console.log("kleines büro ready ...");
const canvas = document.getElementById("banner");
const target = textToCoords("KLEINES BÜRO", 20, alphabet);
const wiggler = new Wiggler(canvas, target);
wiggler.start();
canvas.addEventListener("click", () => { wiggler.mash(); });
new Splide('.splide', {
padding: '5rem',
}).mount();
});