mirror of
https://codeberg.org/vlw/crtjs.git
synced 2025-09-13 18:03:40 +02:00
Working demo
Down on you knees!
This commit is contained in:
parent
3501d1b0fa
commit
fa0c46d5c7
8 changed files with 144 additions and 51 deletions
|
@ -4,7 +4,7 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<title>Cathode Ray</title>
|
||||
<title>CRT</title>
|
||||
<style>
|
||||
:root {
|
||||
/* Screen */
|
||||
|
@ -22,4 +22,4 @@
|
|||
<div id="screen"></div>
|
||||
<script src="js/main.js" type="module"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
44
js/main.js
44
js/main.js
|
@ -1,7 +1,43 @@
|
|||
import { FluorescentScreen } from "./modules/Screen.mjs";
|
||||
import { RasterScan } from "./modules/Gun.mjs";
|
||||
import { RasterScan } from "./modules/ElectronGun.mjs";
|
||||
|
||||
const screen = new FluorescentScreen(document.getElementById("screen"));
|
||||
class CRT {
|
||||
|
||||
const CRT = new RasterScan(screen.pixels);
|
||||
CRT.load("../../tapes/sample");
|
||||
constructor(element) {
|
||||
this.element = element;
|
||||
this.initScreen();
|
||||
this.raster = new RasterScan(this.screen.pixels);
|
||||
}
|
||||
|
||||
async fetchJSON(url) {
|
||||
const response = await fetch(url);
|
||||
return response.json();
|
||||
}
|
||||
|
||||
loadTape(ref) {
|
||||
this.fetchJSON(ref + "/header.json").then(headers => {
|
||||
// Reinitialize player with resolution from tape header
|
||||
if(headers.resolution[0] !== this.element.clientWidth || headers.resolution[1] !== this.element.clientHeight) {
|
||||
this.element.style.setProperty("width",headers.resolution[0] + "px");
|
||||
this.element.style.setProperty("height",headers.resolution[1] + "px");
|
||||
this.initScreen();
|
||||
this.raster.pixels = this.screen.pixels;
|
||||
}
|
||||
|
||||
this.raster.load(headers);
|
||||
});
|
||||
}
|
||||
|
||||
play() {
|
||||
this.raster.playstate("play");
|
||||
}
|
||||
|
||||
initScreen() {
|
||||
this.screen = new FluorescentScreen(this.element);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
window.video = new CRT(document.getElementById("screen"));
|
||||
window.video.loadTape("tapes/sample");
|
||||
window.video.play();
|
||||
|
|
31
js/modules/ElectronGun.mjs
Normal file
31
js/modules/ElectronGun.mjs
Normal file
|
@ -0,0 +1,31 @@
|
|||
export class RasterScan {
|
||||
|
||||
constructor(pixels) {
|
||||
this.pixels = pixels;
|
||||
this.signal = new Worker("./js/modules/Raster.mjs");
|
||||
|
||||
this.signal.addEventListener("message",event => {
|
||||
this.fire(event.data);
|
||||
});
|
||||
}
|
||||
|
||||
fire(pixel) {
|
||||
this.pixels[pixel.index].style.setProperty("background",pixel.color);
|
||||
//this.pixels[data.pixel].style.setProperty("animation",`decay 10ms ${data.pixel} linear forwards`);
|
||||
}
|
||||
|
||||
load(headers) {
|
||||
this.signal.postMessage({
|
||||
type: "headers",
|
||||
payload: headers
|
||||
});
|
||||
}
|
||||
|
||||
playstate(state) {
|
||||
this.signal.postMessage({
|
||||
type: "playstate",
|
||||
payload: state
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
export class RasterScan {
|
||||
|
||||
constructor(pixels) {
|
||||
this.pixels = pixels;
|
||||
this.coils = new Worker("./js/modules/Raster.mjs");
|
||||
|
||||
this.coils.addEventListener("message",event => {
|
||||
this.fire(event.data);
|
||||
});
|
||||
}
|
||||
|
||||
fire(data) {
|
||||
this.pixels[data.pixel].style.setProperty("background",data.color);
|
||||
this.pixels[data.pixel].style.setProperty("animation",`decay 10ms ${data.pixel} linear forwards`);
|
||||
}
|
||||
|
||||
load(tape) {
|
||||
this.coils.postMessage({
|
||||
density: this.pixels.length,
|
||||
tape: tape
|
||||
});
|
||||
}
|
||||
|
||||
}
|
4
js/modules/Helper.mjs
Normal file
4
js/modules/Helper.mjs
Normal file
|
@ -0,0 +1,4 @@
|
|||
export async function fetchJSON(url) {
|
||||
const response = await fetch(url);
|
||||
return response.json();
|
||||
}
|
|
@ -1,17 +1,16 @@
|
|||
let field;
|
||||
let clock;
|
||||
let meta = {
|
||||
fields: 0,
|
||||
pixels: 0,
|
||||
framerate: 100
|
||||
};
|
||||
|
||||
let tape = {
|
||||
header: (data) => {
|
||||
clock = data.framerate;
|
||||
this.format = format;
|
||||
let clock = null;
|
||||
|
||||
self.postMessage({
|
||||
type: "resolutionUpdate",
|
||||
data: resolution
|
||||
});
|
||||
},
|
||||
stream: []
|
||||
let tape = null;
|
||||
let stream = (stream) => {
|
||||
meta.fields = Math.floor(stream.length / meta.pixels);
|
||||
tape = stream;
|
||||
return true;
|
||||
}
|
||||
|
||||
async function fetchJSON(url) {
|
||||
|
@ -19,11 +18,47 @@ async function fetchJSON(url) {
|
|||
return response.json();
|
||||
}
|
||||
|
||||
function loadTape(ref) {
|
||||
fetchJSON(ref + "/header.json").then(data => tape.header(data));
|
||||
fetchJSON(ref + "/data.json").then(data => tape.stream = data);
|
||||
function scan() {
|
||||
let pixel = 0;
|
||||
|
||||
for(let head = 0; head < tape.length; head++) {
|
||||
if(pixel == meta.pixels) {
|
||||
pixel = 0;
|
||||
}
|
||||
|
||||
self.postMessage({
|
||||
index: pixel,
|
||||
color: tape[head]
|
||||
});
|
||||
|
||||
pixel++;
|
||||
}
|
||||
}
|
||||
|
||||
function playstate(state) {
|
||||
if(state == "play") {
|
||||
clock = setInterval(scan,meta.framerate);
|
||||
return;
|
||||
}
|
||||
clock = null;
|
||||
}
|
||||
|
||||
self.addEventListener("message",event => {
|
||||
loadTape(event.data.tape);
|
||||
});
|
||||
const payload = event.data.payload;
|
||||
|
||||
switch(event.data.type) {
|
||||
case "headers":
|
||||
meta.pixels = payload.resolution[0] * payload.resolution[1];
|
||||
meta.framerate = payload.framerate;
|
||||
|
||||
const segmentURL = new Array("../../tapes",payload.manifest,payload.segments[0]).join("/");
|
||||
fetchJSON(segmentURL).then(tape => stream(tape));
|
||||
break;
|
||||
|
||||
case "playstate":
|
||||
playstate(payload);
|
||||
break;
|
||||
|
||||
default: console.warn("Unknown instruction: " + event.data.type); break;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@ export class FluorescentScreen {
|
|||
this.screen = screen;
|
||||
this.pixels = [];
|
||||
|
||||
this.destroyPixels();
|
||||
this.spawnPixels();
|
||||
}
|
||||
|
||||
|
@ -26,4 +27,10 @@ export class FluorescentScreen {
|
|||
this.createMatrix();
|
||||
}
|
||||
|
||||
}
|
||||
destroyPixels() {
|
||||
while(this.screen.firstChild) {
|
||||
this.screen.removeChild(this.screen.lastChild);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
{
|
||||
"manifest": "sample",
|
||||
"format": "signed-hex",
|
||||
"resolution": ["64","64"],
|
||||
"framerate": 10
|
||||
}
|
||||
"resolution": ["32","32"],
|
||||
"framerate": 100,
|
||||
"segments": [
|
||||
"data.json"
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue