RosettaCodeData/Task/Matrix-digital-rain/JavaScript/matrix-digital-rain.js

133 lines
3.7 KiB
JavaScript

var tileSize = 20;
// a higher fade factor will make the characters fade quicker
var fadeFactor = 0.05;
var canvas;
var ctx;
var columns = [];
var maxStackHeight;
function init() {
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
// https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver
const resizeObserver = new ResizeObserver(entries =>
{
for (let entry of entries)
{
if (entry.contentBoxSize)
{
// Firefox implements `contentBoxSize` as a single content rect, rather than an array
const contentBoxSize = Array.isArray(entry.contentBoxSize) ? entry.contentBoxSize[0] : entry.contentBoxSize;
canvas.width = contentBoxSize.inlineSize;
canvas.height = window.innerHeight;
initMatrix();
}
}
});
// observe the size of the document
resizeObserver.observe(document.documentElement);
// start the main loop
tick();
}
function initMatrix() {
columns = [];
maxStackHeight = Math.ceil(canvas.height/tileSize);
// divide the canvas into columns
for (let i = 0 ; i < canvas.width/tileSize ; ++i) {
var column = {};
// save the x position of the column
column.x = i*tileSize;
// create a random stack height for the column
column.stackHeight = 10+Math.random()*maxStackHeight;
// add a counter to count the stack height
column.stackCounter = 0;
// add the column to the list
columns.push(column);
}
}
function draw() {
// draw a semi transparent black rectangle on top of the scene to slowly fade older characters
ctx.fillStyle = "rgba(0 , 0 , 0 , "+fadeFactor+")";
ctx.fillRect(0 , 0 , canvas.width , canvas.height);
ctx.font = (tileSize-2)+"px monospace";
ctx.fillStyle = "rgb(0 , 255 , 0)";
for (let i = 0 ; i < columns.length ; ++i) {
// pick a random ascii character (change the 94 to a higher number to include more characters)
var randomCharacter = String.fromCharCode(33+Math.floor(Math.random()*94));
ctx.fillText(randomCharacter , columns[i].x , columns[i].stackCounter*tileSize+tileSize);
// if the stack is at its height limit, pick a new random height and reset the counter
if (++columns[i].stackCounter >= columns[i].stackHeight)
{
columns[i].stackHeight = 10+Math.random()*maxStackHeight;
columns[i].stackCounter = 0;
}
}
}
// MAIN LOOP
function tick() {
draw();
setTimeout(tick , 50);
}
var b_isFullscreen = false;
function fullscreen() {
var elem = document.documentElement;
if (elem.requestFullscreen) {
elem.requestFullscreen();
}
else if (elem.webkitRequestFullscreen) {
elem.webkitRequestFullscreen(); // Safari
}
else if (elem.msRequestFullscreen) {
elem.msRequestFullscreen(); // IE11
}
}
function exitFullscreen() {
if (document.exitFullscreen) {
document.exitFullscreen();
}
else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen(); // Safari
}
else if (document.msExitFullscreen) {
document.msExitFullscreen(); // IE11
}
}
function toggleFullscreen() {
if (!b_isFullscreen) {
fullscreen();
b_isFullscreen = true;
}
else {
exitFullscreen();
b_isFullscreen = false;
}
}
function updateTileSize() {
tileSize = Math.min(Math.max(document.getElementById("tileSize").value , 10) , 100);
initMatrix();
}
function updateFadeFactor() {
fadeFactor = Math.min(Math.max(document.getElementById("fadeFactor").value , 0.0) , 1.0);
initMatrix();
}