CRT
by phloe
CSS
canvas {
image-rendering: pixelated;
_transform: scale(3);
}
JavaScript
(async () => {
const width = 800;
const height = 600;
const pixelSize = 4;
function setContext(canvas) {
const context = canvas.getContext("2d");
canvas.context = context;
}
function createCanvas(width, height) {
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
setContext(canvas);
return canvas;
}
const canvas = createCanvas(width, height);
document.body.appendChild(canvas);
function loadImg(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = "anonymous";
img.addEventListener("load", () => {
resolve(img);
}, false);
img.addEventListener("error", () => {
console.log("img failed loading");
reject(img);
}, false);
img.src = url;
});
}
async function loadImgToCanvas(url) {
try {
const img = await loadImg(url);
const canvas = createCanvas(img.width, img.height);
canvas.context.drawImage(img, 0, 0);
return canvas;
} catch(e) {
console.log("loadImgToCanvas failed");
}
}
const lowBuffer = createCanvas(width / 8, height / 8);
const maskCell = createCanvas(5, 4);
maskCell.context.fillStyle = "#000";
maskCell.context.fillRect(3, 0, 2, 3);
maskCell.context.fillRect(0, 3, 5, 1);
maskCell.context.fillStyle = "#0004";
maskCell.context.fillRect(0, 0, 1, 1);
maskCell.context.fillRect(2, 0, 1, 1);
maskCell.context.fillRect(2, 2, 1, 1);
maskCell.context.fillRect(0, 2, 1, 1);
const maskPattern = createCanvas(10, 4);
maskPattern.context.drawImage(maskCell, 0, 0);
maskPattern.context.drawImage(maskCell, 5, -2);
maskPattern.context.drawImage(maskCell, 5, 2);
const phosphorCell = createCanvas(5, 4);
phosphorCell.context.fillStyle = "#F00";
phosphorCell.context.fillRect(0, 0, 1, 3);
phosphorCell.context.fillStyle = "#0F0";
phosphorCell.context.fillRect(1, 0, 1, 3);
...