Abfahrtsanzeiger Display Basic Library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
libmonoformat/ts/index.html

209 lines
5.6 KiB

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>MonoDisplay Test</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: #111;
color: #ccc;
font-family: monospace;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
gap: 20px;
padding: 20px;
}
h1 {
font-size: 14px;
letter-spacing: 0.15em;
color: #555;
text-transform: uppercase;
}
/*
* Display container: holds the canvas at a fixed 2:1 aspect ratio (160:80).
* Canvas internal resolution stays at 160×80 logical pixels.
* CSS stretches it to fill this box — image-rendering: pixelated keeps crisp edges.
* To resize the on-screen display: change max-width here. Driver is unaffected.
*/
#display-box {
width: 100%;
max-width: 800px;
aspect-ratio: 2 / 1;
background: #000;
border: 2px solid #333;
border-radius: 4px;
overflow: hidden;
position: relative;
}
#canvas_root {
width: 100%;
height: 100%;
display: block;
image-rendering: pixelated;
image-rendering: crisp-edges; /* Firefox */
}
#resolution {
position: absolute;
bottom: 6px;
right: 8px;
font-size: 10px;
color: #333;
pointer-events: none;
}
#controls {
display: flex;
flex-wrap: wrap;
gap: 8px;
justify-content: center;
}
#controls button {
background: #1a1a1a;
color: #888;
border: 1px solid #333;
border-radius: 3px;
padding: 6px 14px;
font-family: monospace;
font-size: 12px;
cursor: pointer;
transition: background 0.1s, color 0.1s;
}
#controls button:hover { background: #222; color: #bbb; }
#controls button.active { background: #1e3a1e; color: #33ff66; border-color: #33ff66; }
#status { font-size: 11px; color: #444; min-height: 1em; }
</style>
</head>
<body>
<h1>MonoDisplay — 160 × 80</h1>
<div id="display-box">
<!-- Internal res = displayWidth × displayHeight (160×80). CSS does the upscaling. -->
<canvas id="canvas_root" width="160" height="80"></canvas>
</div>
<div id="controls"></div>
<div id="status">select a demo</div>
<!--
Build the library first: bun run build
Produces public/mono-display.js — exposes all types on window.MonoDisplay.
Then serve index.html from any static file server (or file:// directly).
-->
<script src="./public/mono-display.js"></script>
<script>
(function() {
const { MonoDisplayDriver, MonoDisplayFile, ElementType } = window.MonoDisplay;
const driver = new MonoDisplayDriver("canvas_root", {
onColor: "#EC0",
offColor: "#000",
fps: 25,
});
const W = 160, H = 80;
const demos = [
{
label: "Checkerboard (static)",
make() {
const pixels = new Uint8Array(W * H);
for (let y = 0; y < H; y++)
for (let x = 0; x < W; x++)
pixels[y * W + x] = (x + y) % 2;
return new MonoDisplayFile({
width: W, height: H,
elements_always: [{ type: ElementType.Image2D, pixels, width: W, height: H }],
}).toBuffer();
},
},
{
label: "Blink (animation)",
make() {
return new MonoDisplayFile({
elements_always: {
flags: { drawFront: true, clearBuffer: true },
elements: [{
type: ElementType.Animation,
width: W, height: H,
updateInterval: 12, // every 13 ticks ≈ 500ms per frame at 25fps
frames: [
{ pixels: new Uint8Array(W * H).fill(1) },
{ pixels: new Uint8Array(W * H).fill(0) },
],
}],
},
}).toBuffer();
},
},
{
label: "Text (centered)",
make() {
return new MonoDisplayFile({
elements_always: {
flags: { drawFront: true, clearBuffer: true },
elements: [{
type: ElementType.ClippedText,
text: "Hello, World!",
xOffset: 0, yOffset: 32,
width: W, height: 16,
}],
},
}).toBuffer();
},
},
{
label: "Scrolltext (left)",
make() {
return new MonoDisplayFile({
elements_always: {
flags: { drawFront: true, clearBuffer: true },
elements: [{
type: ElementType.HScrollText,
text: "MONO DISPLAY — scrolling ticker — 🚀 ",
xOffset: 0, yOffset: 32,
width: W, height: 16,
scrollSpeed: 50,
flags: { endless: true, invertDirection: false },
}],
},
}).toBuffer();
},
},
];
const controls = document.getElementById("controls");
let activeBtn = null;
for (const demo of demos) {
const btn = document.createElement("button");
btn.textContent = demo.label;
btn.onclick = () => {
if (activeBtn) activeBtn.classList.remove("active");
btn.classList.add("active");
activeBtn = btn;
driver.load(() => Promise.resolve(demo.make()));
};
controls.appendChild(btn);
}
controls.firstElementChild.click();
})();
</script>
</body>
</html>