How To Use Html5 Canvas & JavaScript To Implement The 404 Page Of The Snowflake Screen

This article will show you an example of how to use the Html5 canvas object + javascript to implement the 404 file not found error page with snowflakes on the screen. The sentence on the page is 404 File Not Found which has green color. The text will change it’s transparency value periodically to make it flicker. And there are also some flicker blue wavebands on the screen which seem like zero markings. And the screen is full of snowflakes like old TV which can not receive signals.

1. How To Use Html5 Canvas & JavaScript To Implement The 404 Page Of The Snowflake Screen Example.

  1. Below is the example screen image.
    html5-javascript-snowflake-404-error-page
  2. There are 3 files in this example as below.
    html5-canvas-snowflake-404-page.html
    snowflake-404-page.css
    snowflake-404-page.js
  3. Below is the source code of the above 3 files, please see the code comments to learn how it works.
  4. But you should upload the above 3 files to a local web server and browse the Html file html5-canvas-snowflake-404-page.html in the web browser using the URL http://localhost:8000/html5-canvas-snowflake-404-page.html, otherwise, you will encounter the error message Access to script at …… from origin ‘null’ has been blocked by CORS policy when you browse it, you can read the article How To Fix Error Access To Script At From Origin ‘null’ Has Been Blocked By Cors Policy: Cross Origin Requests Are Only Supported For Protocol Schemes: Http, Data, Chrome, Chrome-extension, Chrome-untrusted, Https to learn how to fix it.
  5. html5-canvas-snowflake-404-page.html.

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>How To Use Html5 Canvas JavaScript To Implement The 404 Page Of The Snowflake Screen</title>
    
    <!-- include the css stylesheet file -->
    <link rel="stylesheet" href="snowflake-404-page.css" />
    
    </head>
    <body>
    
    <!-- define the div and canvas objects. -->
    <div class="content">
        <canvas id="canvas"></canvas>
    </div>
    
    <!-- include the js file, you should write this line of code below the canvas definition above,
     otherwise it will throw the error message this.canvas is null in the javascript code, 
     you can see this error in the web browser inspector. -->
    <script type="text/javascript" src="snowflake-404-page.js" ></script>
    
    </body>
    </html>
  6. snowflake-404-page.css.
    @charset "utf-8";
    
    /* Define the general css style. */
    * {
        padding: 0;
        margin: 0;
    }
    
    
    /* Define the html, body tag's css style. */
    html,
    body {
        width: 100%;
        height: 100vh;
        /* 
        Set to hidden to clip the overflowed content. 
        The overflow's value can be visible, hidden, scroll, auto.'*/
        overflow: hidden; 
        
        /*
        The relative means you can specify the left, top, width, height value 
        relative to the parent element.
        The position's value can be static, relative, fixed, absolute, sticky.
        */
        position: relative;
        font-size: 12px;
    }
    
    
    /* Define the Html element's css style which id is 'canvas'. */
    #canvas {
        width: 100%;
        height: 100%;
        
        /* The canvas's position is absolute, so you should specify the top, left, right, bottom values. */
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        
        /* Define the z-index level of the Html element layer, bigger value's layer will be shown on the top. */
        z-index: 1;
    }
    
    
    /* Define the Html element's css style which class attribute's name is 'content' */
    .content {
    
        /* This Html element should be displayed over canvas element. */
        z-index: 9;
        
        width: 100%;
        height: 100%;
        
        /* Displays this element as a flex container of the block-level. */
        display: flex;
        
        /* Set the default alignment to center for all the flexible container wrapped elements. */
        align-items: center;
        
        /* Aligns the items in the flexible container to center 
           when not all horizontal available spaces are used by the items. */
        justify-content: center;
        
        /* Set the element's background color to transparent. */
        background-color: transparent;
    }
    
    /* Insert some content after the Html element (which uses the content css class) content*/
    .content::after {
        /* Insert an empty string. */
        content: "";
        
        /* Set display style to block to occupy the whole window width. */
        display: block;
        
        /* Set the content position to absolute. */
        position: absolute;
        
        /* Specify the top, bottom, left, right value of the content rectangle. */
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        
        /* Set the layer on the most top of the window. */
        z-index: 99;
        
        /*
        Set the radial gradient background, leave a little white space in the middle, 
        in order to make the display text more clear at a glance.
         */
        background: radial-gradient(
            /* The radial shape is ellipse and is located at the center. */
            ellipse at center,
            
            /* The start color. */
            rgba(0, 0, 0, 0) 0%,
            
            /* The stop color. */
            rgba(0, 0, 0, 0.6) 100%
        );
    }
    
  7. snowflake-404-page.js.
    /**
     * 
     This class is used to implement the snowflake 404 page effect.
     */
    class SnowFlakeApp {
      
      // Below is the constructor method of the SnowFlakeApp class.
      constructor() {
        // Define the instance variables.
        
        // The canvas object.
        this.canvas = null;              
        
        // The context object.
        this.ctx = null;                
        
        // The width of the canvas.
        this.w = 0;                     
        
        // The height of the canvas.
        this.h = 0;                     
        
        // This variable is used to save the background band wave offset value.
        this.offset = 0;                
        
        // Save the canvas ImageData object.
        this.imgData = null;            
        
        // The drawn text, 404 means the HTTP 404 error.
        this.text = "404 File Not Found";              
        
        // The draw text transparent value.
        this.alpha = 0;
        
        // The draw text transparency falloff delta value.                 
        this.alphaNum = 0.005; 
        
        // The maximize draw text transparency value.         
        this.alphaMax = 0.35;  
                 
        this.init();
      }
      
      // The initialize function.
      init() {
        // Get the canvas Html5 element by id. 
        this.canvas = document.getElementById("canvas");
        
        // Get the canvas 2d context object.
        this.ctx = this.canvas.getContext("2d");
        
        // Add the event listener to process the resize event, 
        // when the resize event happen, it will invoke the reset() function. 
        window.addEventListener("resize", this.reset.bind(this));
        
        // call the reset() function to reset the screen.
        this.reset();
        
        // call the render() function to render the web page screen.
        this.render();
      }
      
      // This function will be invoked when user resize the web browser window.
      reset() {
      
        // Reset the object's w, h variable to the web browser's width and height.
        this.w = this.canvas.width = this.ctx.width = window.innerWidth;
        this.h = this.canvas.height = this.ctx.height = window.innerHeight;
        
        // Get and return the Canvas object's context's ImageData object.
        this.changeImgData()
      }
      
    
      // This function will return the canvas context's ImageData object. 
      changeImgData() {
      
        // Get the w, h, ctx instance variables of this object.
        const {w, h, ctx} = this;
        
        // Set the fill color.
        ctx.fillStyle = 'white';
        
        // Set the rectangle by it's top, left, width, height value to fill.
        ctx.fillRect(0, 0, w, h);
        
        // Fill the rectangle with the white color.
        ctx.fill();
        
        // Call the ctx.getImageData(left, top, width, height) method to get and 
        // return the ImageData object which contains the rectangle area pixel data.
        // You can get all rectangle pixels data in the imageData object.
        // The ImageData object's data property is used to hold the pixel's RGBA (Red, Green, Blue, Alpha Transparency) value.
        // So the first pixel's RGBA value is red = imgData.data[0], green = imgData.data[1], blue = imgData.data[2], alpha = imgData.data[3].
        // the second pixel's RGBA value is red = imgData.data[4], green = imgData.data[5], blue = imgData.data[6], alpha = imgData.data[7].
        var imageData = ctx.getImageData(0, 0, w, h);
        this.imgData = imageData;
        
        // Return the ImageData object.
        return this.imgData;
      }
      
      // Render the screen.
      render() {
        this.step();
      }
      
      
      /* This function will draw the snowflake background screen. */
      drawBackground() {
        // Get the instance's ctx and imgData variables.
        const {ctx, imgData} = this;
        
        // Loop the imgData.data property, the data property is a list that contains all the ImageData pixels RGBA value.
        // For the first pixel, red = imgData.data[0], green = imgData.data[1], blue = imgData.data[2], alpha = imgData.data[3].
        // For the second pixel, red = imgData.data[4], green = imgData.data[5], blue = imgData.data[6], alpha = imgData.data[7].
        for (let i = 0, data = imgData.data; i < data.length; i += 4) {
            
            // Create a random color value.
            let color = Math.floor(Math.random() * 255) + 50;
            
            // Assign the same color value to the red, green, blue value, 
            // then the mixed color is between white and black.
            data[i] = color; // assign the red color.
            data[i + 1] = color; // assign the green color.
            data[i + 2] = color; // assign the blue color.
        }
        
        // Put the changed ImageData object back to the canvas context object.
        ctx.putImageData(imgData, 0, 0);
      }
      
      
      // Draw the background band wave, the waved band color is blue.
      drawWaveBand(delta) {
        // Set the delta value to 0 for the first call by the window.requestAnimationFrame() function.
        if(delta == null){
        
           delta = 0
        
        }
        
        this.offset = delta / 10;
        
        const {w, h, ctx} = this;
        
        for (let y = -h / 5, v = h / 5; y < h; y += v) {
          
          ctx.fillStyle = `rgba(0,0,0,${(this.alphaMax - this.alpha) / 8 + 0.02})`;
          
          ctx.shadowColor = "blue";
          
          ctx.shadowBlur = 20;
          
          ctx.fillRect(0, y + this.offset % v, w, v / 2);
        }
      }
      
      
    
      // Draw the 404 file not found error text.
      drawText() {
        
        // Calculate the text alpha value number.
        // Add the this.alphaNum to the this.alpha. 
        this.alpha += this.alphaNum;
        // If the text alpha value is bigger than alphaMax then reduce it.
        if (this.alpha >= this.alphaMax) {
            this.alpha = this.alphaMax;
            this.alphaNum *= -1;
        } 
        // If the draw text alpha value is negative, then increase the alpha number. 
        else if (this.alpha < 0) {
            this.alpha = 0;
            this.alphaNum *= -1;
        }
        
        // Get the instance's variables.
        const {ctx, text, w, h} = this;
        
        // Set the font size to 0.08 * web-browser-window-width.
        let fontSize = w * 0.08;
        
        // Save the current context's state to the stack.
        ctx.save();
        
        // Set the canvas filled color.
        ctx.fillStyle = `rgba(0,0,0,${this.alpha})`
        
        // Set the canvas text content's font.
        ctx.font = `bold ${fontSize}px fantasy, monospace`;
        
        // Align the canvas text content to center when draw it. 
        ctx.textAlign = "center";
        
        // Set the context text baseline for drawing text.
        ctx.textBaseline = 'middle';
        
        // Set the shadow color for the text.
        ctx.shadowColor = "green";
        
        // Set the text shadow blur level number.
        ctx.shadowBlur = 20;
        
        // Fill the text, start from w/2, h/2, because set the ctx.textAlign = "center", 
        // then the text center will be aligned at the browser window's center horizontally.
        ctx.fillText(text, w / 2, h / 2);
        
        // Restore the previous saved canvas context state from the stack.
        ctx.restore();
      }
      
      /* 
        This function is called to redraw the web page screen.
        Because the function step(delta) is a callback function of the function window.requestAnimationFrame(this.step.bind(this)),
        then the window.requestAnimationFrame() function will pass the current time value in milliseconds to the callback function.
        You can see more in the URL https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame.
      */
      step(delta) {
        
        // Get the object's w, h, ctx variable. 
        const {w, h, ctx} = this;
        
        // Call the window.requestAnimationFrame() function to perform an animation.
        // The web browser will call the this.step() function (the callback function) before the next repaint.
        // Because the step() function call the window.requestAnimationFrame(callback) function again so this is similar to setInterval.
        // The callback function will be reinvoked every 1/60 seconds because the web browser will repaint 60 times in one second.
        window.requestAnimationFrame(this.step.bind(this));
        
        // Clear the web page rectangle ( the whole web browser window ). 
        ctx.clearRect(0, 0, w, h);
        
        // Draw the web page background. 
        this.drawBackground();
        
        // Draw the 404 text.
        this.drawText();
        
        // Draw the background wave band.
        this.drawWaveBand(delta);
      }
    }
    
    // Create a SnowFlakeApp instance when the window is loaded. 
    window.onload = new SnowFlakeApp();

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.