Run Save Upload File Fullscreen About
<canvas id="canvas" width="640" height="400"></canvas>
<canvas id="dummyCanvas" width="640" height="400"></canvas>
<audio loop id="audio-effect">
	<source src="/tv-snow/effect.ogg" type="audio/ogg">
	<source src="/tv-snow/effect.mp3" type="audio/mpeg">
	Votre navigateur ne peut pas lire l'audio !
</audio>
body {
    margin: 0;
    padding: 0;
    overflow: hidden;
    background-color: #272727;
}

#canvas {
    filter: blur(0.37vh);
    position: absolute;
    width: calc(100vw - 2vh);
    height: calc(100vh - 2vh);
    border: 1vh solid #272727;
    border-radius: 5vh;
}

#dummyCanvas {
    display: none;
}
// Get datas
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext( '2d' );

// Settings
var black = "#272727";
var white = "#E6E6E6";
var frameRate = 15;

var last = black;
var volume = 10; // Current volume
var shouldDrawVolume = false; // Draw volume in current frame
var volumeDisplayTime = 3000; // Time to display volume (in milli-seconds)
var stopSoundTimeout = null;
var audio = document.getElementById("audio-effect");
audio.volume = 0.5;
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);

// First we check the drawing speed
var dummyCanvas = document.getElementById("dummyCanvas");
var dummyCtx = dummyCanvas.getContext("2d");
var t0 = performance.now();
drawSnow(dummyCtx, dummyCanvas);
drawLines(dummyCtx, dummyCanvas);
var t1 = performance.now();

// Listen up for volume up and down
addEvent(document, "keypress", function (e) {
    e = e || window.event;
    var charCode = (typeof e.which == "number") ? e.which : e.keyCode;
    if (charCode == 43) {
        if (volume < 20) {
            volume++;
            audio.volume = volume / 20;
        }
        shouldDrawVolume = true;
        if (stopSoundTimeout !== null) {
            clearTimeout(stopSoundTimeout);
        }
        stopSoundTimeout = setTimeout(function() {
            shouldDrawVolume = false;
            stopSoundTimeout = null;
        }, volumeDisplayTime);
    } else if (charCode == 45) {
        if (volume > 0) {
            volume--;
            audio.volume = volume / 20;
        }
        shouldDrawVolume = true;
        if (stopSoundTimeout !== null) {
            clearTimeout(stopSoundTimeout);
        }
        stopSoundTimeout = setTimeout(function() {
            shouldDrawVolume = false;
            stopSoundTimeout = null;
        }, volumeDisplayTime);
    }
});

if (t1 - t0 > 150) {
    
    // If the computer is too slow, we generate 20 pictures before in a dummy canvas
    console.log("Browser too slow, loading....");
    var currentPic = 0;
    var frame5 = []; // The name "frames" is reserved by JavaScript
    var generationInterval = setInterval(function() {
        
        // Save the last
        // Warning: The first picture is generated in the real canvas!
        frame5[currentPic] = dummyCtx.getImageData(0, 0, dummyCanvas.width, dummyCanvas.height);
    
        // Draw a "no signal" message while loading
        displayLoading(ctx, canvas);
        
        currentPic++;
        if (currentPic > 20) {
            
            // Stop generation
            clearInterval(generationInterval);
            
            // Run audio
            audio.play();
            
            // Set up the drawing interval
            var currentFrame = 0;
            setInterval(function() {
                if (frame5.length > 0) {
                    ctx.putImageData(frame5[currentFrame], 0, 0);
                    if (shouldDrawVolume) {
                        drawVolume(ctx, canvas);
                    }
                    currentFrame++;
                    if (currentFrame == frame5.length) {
                        currentFrame = 0;
                    }
                }
            }, 1000 / frameRate);
            
        } else {
            // Generate the next
            drawSnow(dummyCtx, dummyCanvas);
            drawLines(dummyCtx, dummyCanvas);
        }
    }, 10);
    
} else {

    // Run audio
    audio.play();
    
    // If the computer is as fast, we can generate a new pitcure for every frame
    setInterval(function () {
        drawSnow(ctx, canvas);
        drawLines(ctx, canvas);
        if (shouldDrawVolume) {
            drawVolume(ctx, canvas);
        }
    }, 1000 / frameRate);
    
}

function drawSnow(ctx, canvas) {
    var line = Math.floor(Math.random() * 3);
    for (var i = 0; i < canvas.height; i++) {
        for (var j = 0; j < canvas.width; j++) {
            if ((i + line) % 3 !== 0) {
                if (last == white) {
                    if (Math.random() < 0.65) {
                        ctx.fillStyle = white;
                        last = white;
                    } else {
                        ctx.fillStyle = black;
                        last = black;
                    }
                } else {
                    if (Math.random() < 0.5) {
                        ctx.fillStyle = white;
                        last = white;
                    } else {
                        ctx.fillStyle = black;
                        last = black;
                    }
                }
            } else {
                if (Math.random() < 0.25) {
                    ctx.fillStyle = white;
                } else {
                    ctx.fillStyle = black;
                }
            }
            ctx.fillRect(j, i, 1, 1);
        }
    }
}

function drawLines(ctx, canvas) {
    ctx.fillStyle = "rgba(39, 39, 39, 0.5)";
    for (var i = 0; i < Math.random()*10; i++) {
        var start = Math.floor(Math.random() * canvas.height);
        var height = Math.floor(Math.random() * (canvas.height/10));
        ctx.fillRect(0, start, canvas.width, height);
    }
}

// Displays a loading text
function displayLoading(ctx, canvas) {
    // Put the text
    ctx.fillStyle = "black";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.font = (canvas.height / 15) + "px MonoSpace";
    ctx.fillStyle = "#00FF00";
    ctx.textAlign = "center";
    ctx.fillText("no signal", canvas.width/2, canvas.height/2 - (canvas.height / 20));
    ctx.fillText("please wait...", canvas.width/2, canvas.height/2 + (canvas.height / 20));
}

// Displays the volume
function drawVolume(ctx, canvas) {
    var left = canvas.width / 3;
    var top = canvas.height - (canvas.height / 6);
    var onWidth = left / 20;
    var offWidth = left / 40;
    var height = canvas.height / 20;
    ctx.fillStyle = "#00FF00";
    for (var i = 0; i < 20; i++) {
        ctx.fillRect(left + (i * onWidth), top, (i < volume ? onWidth + offWidth : offWidth), height);
    }
    ctx.beginPath();
    ctx.moveTo(left - (canvas.height / 10), top + height);
    ctx.lineTo(left - onWidth, top + height);
    ctx.lineTo(left - onWidth, top);
    ctx.closePath();
    ctx.fill();
}

// Cross-browser eventer
function addEvent(element, eventName, callback) {
    if (element.addEventListener) {
        element.addEventListener(eventName, callback, false);
    } else if (element.attachEvent) {
        element.attachEvent("on" + eventName, callback);
    } else {
        element["on" + eventName] = callback;
    }
}
JavaScript Console