feat: Change matrix

- Use blocks for now
- Hold and clean for line
- Only one line for now
This commit is contained in:
sthag 2026-03-28 19:44:07 +01:00
parent 8fe884aad6
commit c1633e0bc9

View file

@ -7,255 +7,127 @@ tags:
{% block style %} {% block style %}
<style> <style>
:root {
--space: 16px;
}
html, body { html, body {
height: calc(100vh - calc(var(--space) * 2)); height: 100vh;
box-sizing: border-box; box-sizing: border-box;
} }
body { body {
position: relative; margin: 0;
margin: var(--space); background-color: grey;
/* background-color: grey; */
border: 1px solid black;
font-family: 'Courier New', Courier, monospace; font-family: 'Courier New', Courier, monospace;
} }
.container { #canvas {
background-color: grey; display: block;
} width: 100%;
height: 100%;
.glyph {
position: absolute;
top: 0;
left: 0;
font-size: 24px;
line-height: 1;
font-weight: bold;
} }
</style> </style>
{% endblock %} {% endblock %}
{% block body %} {% block body %}
<canvas id="canvas"> <canvas id="canvas"></canvas>
<div>Canvas element not supported.</div>
</canvas>
<div id="container">
<span id="a" class="glyph">A</span>
</div>
{% endblock %} {% endblock %}
{% block script %} {% block script %}
<script> <script>
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const glyphEls = document.getElementsByClassName('glyph'); const canvas = document.getElementById("canvas");
const glyphEl = document.getElementById('a'); const ctx = canvas.getContext("2d");
const cEl = document.getElementById('container'); const observer = new ResizeObserver(() => {
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
console.log("resize");
});
let createId = undefined; let newId = undefined;
let changeId = undefined;
let holdId = undefined; let holdId = undefined;
let cleanId = undefined; let cleanId = undefined;
let createInterval = 300; let newInterval = 300;
let changeInterval = 300;
let holdInterval = 1000; let holdInterval = 1000;
let cleanInterval = 1000; let cleanInterval = 3000;
let bodyHeight = Math.max(document.body.offsetHeight, document.body.clientHeight, 0);
let glyphY = parseInt(window.getComputedStyle(glyphEl).top);
let glyphW = glyphEl.offsetWidth;
let glyphH = glyphEl.offsetHeight;
let maxHeight = bodyHeight - glyphY - 2 * 16;
let index = 0; let index = 0;
cEl.style.display = 'none'; ctx.font = "24px 'Courier New', Courier, monospace";
function canvasTrail() { let char = characters.charAt(Math.floor(Math.random() * characters.length));
const canvas = document.getElementById("canvas"); let charMeasure = ctx.measureText(char);
const body = document.querySelector("body"); let glyph = {
canvas.width = body.clientWidth - 2; text: char,
canvas.height = body.clientHeight - 2; x: 0,
y: 0,
if (canvas.getContext) { w: Math.ceil(Math.max(charMeasure.actualBoundingBoxLeft + charMeasure.actualBoundingBoxRight, charMeasure.width)),
const ctx = canvas.getContext("2d"); h: charMeasure.fontBoundingBoxDescent + charMeasure.fontBoundingBoxAscent
ctx.font = "24px 'Courier New', Courier, monospace";
// ctx.textBaseline = "top";
let glyphText = "A";
let glyphMeasure = ctx.measureText(glyphText);
let glyphX = 0;
let glyphY = 0;
let glyphW = Math.max(glyphMeasure.actualBoundingBoxLeft + glyphMeasure.actualBoundingBoxRight, glyphMeasure.width);
let glyphH = glyphMeasure.fontBoundingBoxDescent + glyphMeasure.fontBoundingBoxAscent;
let glyph = {
text: glyphText,
measure: glyphMeasure,
x: glyphX,
y: glyphY,
w: glyphW,
h: glyphH
}
let lane = [];
ctx.fillStyle = "grey";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// ctx.fillStyle = "black";
// ctx.fillRect(glyphX, glyphY, glyphW, glyphH);
// ctx.fillStyle = "red";
// ctx.fillText(glyphText, glyphX, glyphY + glyphMeasure.fontBoundingBoxAscent);
ctx.fillStyle = "black";
createId = setInterval(createGlyph, createInterval, ctx, characters, glyph, lane);
} else {
console.log('Canvas element not supported.');
}
} }
let lane = [];
function createGlyph(ctx, chars, glyph, lane) { console.log("init", newInterval);
clearTimeout(cleanId); console.log(glyph);
glyph.text = chars.charAt(Math.floor(Math.random() * chars.length));
console.log(glyph.text, glyph.y);
lane.push([glyph.text, glyph.y]); observer.observe(canvas);
// ctx.fillStyle = "black"; newId = setInterval(newTrail, newInterval);
// ctx.fillRect(glyph.x, glyph.y, glyph.w, glyph.h);
ctx.fillStyle = "white";
ctx.fillText(glyph.text, glyph.x, glyph.y + glyph.measure.fontBoundingBoxAscent);
if (glyph.y >= glyph.h) { function newTrail() {
let prevY = glyph.y - glyph.h;
let bkg = "rgba(128, 128, 128, " + randomBetween(.1, 1) + ")";
ctx.clearRect(glyph.x, prevY, glyph.w, glyph.h);
ctx.fillStyle = "grey";
ctx.fillRect(glyph.x, prevY, glyph.w, glyph.h);
ctx.fillStyle = "black";
ctx.fillText(glyph.text, glyph.x, prevY + glyph.measure.fontBoundingBoxAscent);
ctx.fillStyle = bkg;
ctx.fillRect(glyph.x, prevY, glyph.w, glyph.h);
}
glyph.y += glyph.h;
if (glyph.y > canvas.height) {
// holdLane(ctx, chars, glyph, lane);
clearInterval(createId);
holdId = setTimeout(holdLane, holdInterval, ctx, chars, glyph, lane);
}
}
function holdLane(ctx, chars, glyph, lane) {
console.log("hold");
glyph.y = 0;
// clearInterval(createId);
// Änderung der Transparenz (sehr selten)
// Änderung des Symbols (selten)
cleanId = setTimeout(cleanLane, cleanInterval, ctx, chars, glyph, lane);
}
function cleanLane(ctx, chars, glyph, lane) {
console.log("clean");
clearTimeout(holdId);
lane = [];
ctx.clearRect(glyph.x, glyph.y, glyph.w, canvas.height);
ctx.fillStyle = "grey";
ctx.fillRect(0, 0, glyph.w, canvas.height);
createId = setInterval(createGlyph, randomIntFrom(100, 1000), ctx, chars, glyph, lane);
}
function containerTrail(position, container) {
const laneEl = document.createElement('div');
laneEl.className = 'lane';
container.appendChild(laneEl);
let changeGlyphId = setInterval(() => {
let newEl = glyphEl.cloneNode();
let glyphX = position;
glyphY += glyphEl.clientHeight;
newEl.innerHTML = characters.charAt(Math.floor(Math.random() * characters.length));
newEl.id = '';
newEl.style.top = glyphY + 'px';
newEl.style.left = glyphX + 'px';
newEl.style.opacity = 1;
if (glyphY > maxHeight) {
glyphY = 0;
laneEl.textContent = '';
}
laneEl.appendChild(newEl);
let prevEl = newEl.previousElementSibling;
if (prevEl !== null) {
prevEl.style.opacity = randomBetween(.5, 1);
}
}, createInterval);
}
function addTrails(amount) {
for (let index = 0; index <= amount; index++) {
let position = index * glyphW;
containerTrail(position);
}
}
function getGlyph(fontSize = 24, lineHeight = 1) {
const glyphEl = document.createElement('span');
glyphEl.style = 'glyph';
return glyphEl;
}
function createStyle() {
const stylesheet = document.styleSheets[0];
stylesheet.cssRules[0].style.backgroundColor = "aqua";
}
// containerTrail(0, cEl);
// window.addEventListener("load", canvasTrail);
/**
* Change glyph
*/
console.log("init", changeInterval);
changeId = setInterval(change, changeInterval);
function change() {
clearInterval(holdId); clearInterval(holdId);
let char = characters.charAt(Math.floor(Math.random() * characters.length));
console.log(index, char); glyph.text = characters.charAt(Math.floor(Math.random() * characters.length));
console.log(index, glyph.text);
lane.push([index, glyph.text, glyph.y]);
ctx.fillStyle = "white";
ctx.fillRect(glyph.x, glyph.y, glyph.w, glyph.h);
// ctx.fillText(glyph.text, glyph.x, glyph.y + glyph.h);
if (index > 0) {
let prevY = glyph.y - glyph.h;
ctx.fillStyle = "rgba(0, 0, 0, " + randomBetween(.6, 1) + ")";
ctx.fillRect(glyph.x, prevY, glyph.w, glyph.h);
}
index++; index++;
glyph.y += glyph.h;
if (index > 10) { if (index > 10) {
clearInterval(changeId);
index = 0;
changeInterval = randomIntFrom(100, 1000, 2);
console.clear();
console.log("hold", holdInterval); console.log("hold", holdInterval);
holdId = setTimeout(() => { clearInterval(newId);
holdInterval = randomIntFrom(1000, 10000, 3);
console.log("change", changeInterval); index = 0;
changeId = setInterval(change, changeInterval); glyph.y = 0;
newInterval = randomIntFrom(100, 1000, 2);
holdId = setTimeout(() => {
console.log("clean", cleanInterval);
holdInterval = randomIntFrom(1000, 10000, 3);
cleanId = setInterval(cleanTrail, cleanInterval);
}, holdInterval);
}
}
function cleanTrail() {
clearInterval(holdId);
let pos = lane.shift();
console.log(pos);
ctx.clearRect(0, pos[2], glyph.w, glyph.h);
// ctx.clearRect(0, 0, canvas.width, canvas.height);
if (!lane.length) {
console.log("hold", holdInterval);
clearInterval(cleanId);
holdId = setTimeout(() => {
console.clear();
console.log("new", newInterval);
cleanInterval = randomIntFrom(1000, 10000, 3);
newId = setInterval(newTrail, newInterval);
}, holdInterval); }, holdInterval);
} }
} }