8

My new and improved server-error page

 3 years ago
source link: https://charlesleifer.com/blog/my-new-and-improved-server-error-page/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

My new and improved server-error page

January 08, 2019 09:35 / canvas javascript / 0 comments

I saw an excellent article recently describing how to implement the fire effect seen in the trailer for the N64/PlayStation ports of the DooM game. I figured this would be neat to put on the page displayed whenever there's a server error. I already have an awesome 404 page, and now I'm equally happy with the 500 page.

I made a few small modifications to the code presented in the article. I'm using a back-buffer that is half the size of the canvas, then relying on canvas APIs to scale-up the resulting image. I'm also using the canvas fillText API to add text to the foreground of the canvas.

Check out the effect:

And here is the code:

function Fire(canvas_id, width, height, scale_factor) {
  var scale_factor = (scale_factor ? scale_factor : 2),
      width = (width ? width : 800) / scale_factor,
      height = (height ? height : 600) / scale_factor,
      canvas_id = canvas_id,
      fire_data = [],
      palette = [];

  var fire_colors = [
    0x07,0x07,0x07,
    0x1F,0x1F,0x1F,
    0x2F,0x0F,0x07,
    0x47,0x0F,0x07,
    0x57,0x17,0x07,
    0x67,0x1F,0x07,
    0x77,0x1F,0x07,
    0x8F,0x27,0x07,
    0x9F,0x2F,0x07,
    0xAF,0x3F,0x07,
    0xBF,0x47,0x07,
    0xC7,0x47,0x07,
    0xDF,0x4F,0x07,
    0xDF,0x57,0x07,
    0xDF,0x57,0x07,
    0xD7,0x5F,0x07,
    0xD7,0x5F,0x07,
    0xD7,0x67,0x0F,
    0xCF,0x6F,0x0F,
    0xCF,0x77,0x0F,
    0xCF,0x7F,0x0F,
    0xCF,0x87,0x17,
    0xC7,0x87,0x17,
    0xC7,0x8F,0x17,
    0xC7,0x97,0x1F,
    0xBF,0x9F,0x1F,
    0xBF,0x9F,0x1F,
    0xBF,0xA7,0x27,
    0xBF,0xA7,0x27,
    0xBF,0xAF,0x2F,
    0xB7,0xAF,0x2F,
    0xB7,0xB7,0x2F,
    0xB7,0xB7,0x37,
    0xCF,0xCF,0x6F,
    0xDF,0xDF,0x9F,
    0xEF,0xEF,0xC7,
    0xFF,0xFF,0xFF
  ];

  // Seed palette with fire colors.
  for (var i = 0, l = fire_colors.length / 3; i < l; i++) {
    palette[i] = {
      r: fire_colors[i * 3 + 0],
      g: fire_colors[i * 3 + 1],
      b: fire_colors[i * 3 + 2]
    };
  }

  function init() {
    // Initialize array representing the entire canvas.
    // Set all pixels to palette index 0 (0x07, 0x07, 0x07).
    for (var i = 0; i < width * height; i++) {
      fire_data[i] = 0;
    }

    // Set bottom line to index 36, white.
    for (var i = 0; i < width; i++) {
      fire_data[(height - 1) * width + i] = 36;
    }
  }

  function spread_fire(src) {
    var pixel = fire_data[src];
    if (pixel == 0) {
      // Set pixel above to black.
      fire_data[src - width] = 0;
    } else {
      var randIdx = Math.round(Math.random() * 3.0) & 3;
      var dst = src - randIdx + 1;

      var decrement = (Math.round(Math.random() * 2) < 1) ? 1 : 0;
      fire_data[dst - width] = pixel - decrement;
    }
  }

  function generate_fire() {
    for (var x = 0; x < width; x++) {
      for (var y = 1; y < height; y++) {
        spread_fire(y * width + x);
      }
    }
  }

  // drawing routine
  this.draw = function() {
    // Step the fire.
    generate_fire();

    color = ctx.getImageData(0, 0, width, height);

    for (var y = 0; y < height; y++) {
      for (var x = 0; x < width; x++) {
        var idx = fire_data[y * width + x];
        var pixel = palette[idx];

        var offset = ((width * y) + x) * 4;
        color.data[offset + 0] = pixel.r;
        color.data[offset + 1] = pixel.g;
        color.data[offset + 2] = pixel.b;
      }
    }

    ctx.putImageData(color, 0, 0);
    canvas_ctx.drawImage(buffer, 0, 0);
    canvas_ctx.fillStyle = "#b7b737";
    canvas_ctx.textAlign = "center";
    canvas_ctx.font = "30px sans";
    canvas_ctx.fillText("internal server error", width / 2, height / 2);

    // calculate timeout using level
    t = setTimeout("draw()", 30);
  }

  var buffer = document.createElement("canvas");
  buffer.width = width;
  buffer.height = height;
  var ctx = buffer.getContext('2d');

  var canvas = document.getElementById(canvas_id);
  var canvas_ctx = canvas.getContext('2d');

  // Fill canvas with black pixels.
  canvas_ctx.scale(scale_factor, scale_factor);
  canvas_ctx.imageSmoothingEnabled = false;
  ctx.fillStyle = "#000";
  ctx.fillRect(0, 0, width, height);
  init();

  return this;
}

Comments (0)


Commenting has been closed, but please feel free to contact me


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK