2026-03-28 19:10:45 +01:00
|
|
|
---
|
|
|
|
|
title: Matrix
|
|
|
|
|
tags:
|
|
|
|
|
- demoExample
|
|
|
|
|
---
|
|
|
|
|
{% layout 'hippie/simple.liquid' %}
|
|
|
|
|
|
|
|
|
|
{% block style %}
|
|
|
|
|
<style>
|
|
|
|
|
html, body {
|
2026-03-28 19:44:07 +01:00
|
|
|
height: 100vh;
|
2026-03-28 19:10:45 +01:00
|
|
|
box-sizing: border-box;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
body {
|
2026-03-28 19:44:07 +01:00
|
|
|
margin: 0;
|
2026-03-28 19:10:45 +01:00
|
|
|
background-color: grey;
|
2026-03-28 19:44:07 +01:00
|
|
|
font-family: 'Courier New', Courier, monospace;
|
2026-03-28 19:10:45 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
#canvas {
|
|
|
|
|
display: block;
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
2026-03-28 19:10:45 +01:00
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
{% endblock %}
|
|
|
|
|
|
|
|
|
|
{% block body %}
|
2026-03-28 19:44:07 +01:00
|
|
|
<canvas id="canvas"></canvas>
|
2026-03-28 19:10:45 +01:00
|
|
|
{% endblock %}
|
|
|
|
|
|
|
|
|
|
{% block script %}
|
|
|
|
|
<script>
|
|
|
|
|
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
2026-03-28 19:44:07 +01:00
|
|
|
const canvas = document.getElementById("canvas");
|
|
|
|
|
const ctx = canvas.getContext("2d");
|
|
|
|
|
const observer = new ResizeObserver(() => {
|
|
|
|
|
canvas.width = canvas.clientWidth;
|
|
|
|
|
canvas.height = canvas.clientHeight;
|
|
|
|
|
console.log("resize");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let newId = undefined;
|
2026-03-28 19:10:45 +01:00
|
|
|
let holdId = undefined;
|
|
|
|
|
let cleanId = undefined;
|
2026-03-28 19:44:07 +01:00
|
|
|
let newInterval = 300;
|
2026-03-28 19:21:59 +01:00
|
|
|
let holdInterval = 1000;
|
2026-03-28 19:44:07 +01:00
|
|
|
let cleanInterval = 3000;
|
2026-03-28 19:21:59 +01:00
|
|
|
let index = 0;
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
ctx.font = "24px 'Courier New', Courier, monospace";
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
let char = characters.charAt(Math.floor(Math.random() * characters.length));
|
|
|
|
|
let charMeasure = ctx.measureText(char);
|
|
|
|
|
let glyph = {
|
|
|
|
|
text: char,
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
w: Math.ceil(Math.max(charMeasure.actualBoundingBoxLeft + charMeasure.actualBoundingBoxRight, charMeasure.width)),
|
|
|
|
|
h: charMeasure.fontBoundingBoxDescent + charMeasure.fontBoundingBoxAscent
|
2026-03-28 19:10:45 +01:00
|
|
|
}
|
2026-03-28 19:44:07 +01:00
|
|
|
let lane = [];
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
console.log("init", newInterval);
|
|
|
|
|
console.log(glyph);
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
observer.observe(canvas);
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
newId = setInterval(newTrail, newInterval);
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
function newTrail() {
|
|
|
|
|
clearInterval(holdId);
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
glyph.text = characters.charAt(Math.floor(Math.random() * characters.length));
|
|
|
|
|
console.log(index, glyph.text);
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
lane.push([index, glyph.text, glyph.y]);
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
ctx.fillStyle = "white";
|
|
|
|
|
ctx.fillRect(glyph.x, glyph.y, glyph.w, glyph.h);
|
|
|
|
|
// ctx.fillText(glyph.text, glyph.x, glyph.y + glyph.h);
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
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);
|
|
|
|
|
}
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
index++;
|
|
|
|
|
glyph.y += glyph.h;
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
if (index > 10) {
|
|
|
|
|
console.log("hold", holdInterval);
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
clearInterval(newId);
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
index = 0;
|
|
|
|
|
glyph.y = 0;
|
|
|
|
|
newInterval = randomIntFrom(100, 1000, 2);
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
holdId = setTimeout(() => {
|
|
|
|
|
console.log("clean", cleanInterval);
|
2026-03-28 19:10:45 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
holdInterval = randomIntFrom(1000, 10000, 3);
|
|
|
|
|
cleanId = setInterval(cleanTrail, cleanInterval);
|
|
|
|
|
}, holdInterval);
|
2026-03-28 19:10:45 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
function cleanTrail() {
|
2026-03-28 19:21:59 +01:00
|
|
|
clearInterval(holdId);
|
|
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
let pos = lane.shift();
|
|
|
|
|
console.log(pos);
|
2026-03-28 19:21:59 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
ctx.clearRect(0, pos[2], glyph.w, glyph.h);
|
|
|
|
|
// ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
|
|
|
|
|
|
if (!lane.length) {
|
2026-03-28 19:21:59 +01:00
|
|
|
console.log("hold", holdInterval);
|
|
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
clearInterval(cleanId);
|
|
|
|
|
|
2026-03-28 19:21:59 +01:00
|
|
|
holdId = setTimeout(() => {
|
2026-03-28 19:44:07 +01:00
|
|
|
console.clear();
|
|
|
|
|
console.log("new", newInterval);
|
2026-03-28 19:21:59 +01:00
|
|
|
|
2026-03-28 19:44:07 +01:00
|
|
|
cleanInterval = randomIntFrom(1000, 10000, 3);
|
|
|
|
|
newId = setInterval(newTrail, newInterval);
|
2026-03-28 19:21:59 +01:00
|
|
|
}, holdInterval);
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-03-28 19:10:45 +01:00
|
|
|
|
|
|
|
|
function randomBetween(min, max) {
|
|
|
|
|
return (Math.random() * (max - min) + min).toFixed(2);
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-28 19:21:59 +01:00
|
|
|
function randomIntFrom(min, max, pos = 0) {
|
|
|
|
|
pos = Math.pow(10, pos);
|
2026-03-28 19:10:45 +01:00
|
|
|
min = Math.ceil(min);
|
|
|
|
|
max = Math.floor(max);
|
|
|
|
|
|
2026-03-28 19:21:59 +01:00
|
|
|
return Math.floor((Math.random() * (max - min + 1) + min) / pos) * pos;
|
2026-03-28 19:10:45 +01:00
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
{% endblock %}
|