2024-12-17 07:16:39 +00:00
|
|
|
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;
|
|
|
|
|
2024-12-17 12:33:08 +00:00
|
|
|
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]));
|
2024-12-17 07:16:39 +00:00
|
|
|
|
|
|
|
// this.initRandom();
|
|
|
|
// this.initCorners();
|
2024-12-17 12:33:08 +00:00
|
|
|
this.current = this.initEdges(maxx, maxy);
|
2024-12-17 07:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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() {
|
2024-12-17 12:43:13 +00:00
|
|
|
this.fillStyle = "#C9E6F0"
|
|
|
|
this.ctx.clearRect(0, 0, 800, 600)
|
2024-12-17 07:16:39 +00:00
|
|
|
|
2024-12-17 12:43:13 +00:00
|
|
|
this.ctx.strokeStyle = "white"
|
|
|
|
this.ctx.lineWidth = 3
|
|
|
|
this.ctx.lineJoin = "round"
|
|
|
|
this.ctx.lineCap = "round"
|
2024-12-17 07:16:39 +00:00
|
|
|
|
|
|
|
this.current.forEach(l => {
|
2024-12-17 12:43:13 +00:00
|
|
|
this.ctx.beginPath()
|
|
|
|
this.ctx.moveTo(l[0][0], l[0][1])
|
|
|
|
this.ctx.lineTo(l[1][0], l[1][1])
|
|
|
|
this.ctx.stroke()
|
2024-12-17 07:16:39 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
mash() {
|
2024-12-17 12:33:08 +00:00
|
|
|
// 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
|
|
|
|
}
|
2024-12-17 07:16:39 +00:00
|
|
|
|
|
|
|
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 ...");
|
|
|
|
|
2024-12-17 12:33:08 +00:00
|
|
|
const canvas = document.getElementById("banner");
|
|
|
|
const target = textToCoords("KLEINES BÜRO", 20, alphabet);
|
2024-12-17 07:16:39 +00:00
|
|
|
const wiggler = new Wiggler(canvas, target);
|
|
|
|
|
|
|
|
wiggler.start();
|
|
|
|
|
|
|
|
canvas.addEventListener("click", () => { wiggler.mash(); });
|
|
|
|
|
|
|
|
new Splide('.splide', {
|
|
|
|
padding: '5rem',
|
|
|
|
}).mount();
|
|
|
|
|
|
|
|
});
|