A simple drawing grid with HTML5 part 2

June 5, 2012
A simple drawing grid with HTML5 part 2

Last week we created a full page drawing surface with HTML5 canvas. This week we will add a few simple controls to allow for the user to clear the surface, set drawing colors, and choose different sizes for the ‘pen’.

To make room for some controls, the drawing surface will no longer encompass the entire page. We will also leave the canvas white and style it to have a black border.

Modify the HTML mark-up to look like this

<!DOCTYPE HTML>
<html>
    <style type="text/css">
       html, body {
            width: 100%;
            height: 100%;
            margin: 0;
            display: flex;
            flex-direction: column;
        }
        #grid-container {
            display: flex;
            justify-content: center;
            align-items: center;
            flex: 1;
        }
        #grid {
            border: 1px solid #000;
        }
        #controls {
            display: flex;
            justify-content: center;
            padding: 10px;
            gap: 10px;
        }
        button {
            padding: 5px 10px;
            cursor: pointer;
        }
    </style>
    <body>
        <div id="controls">
            <button onclick="initializeCanvas()">Clear Canvas</button>
            <button onclick="setPenColor('rgb(255,0,0)')">Red</button>
            <button onclick="setPenColor('rgb(0,255,0)')">Green</button>
            <button onclick="setPenColor('rgb(0,0,255)')">Blue</button>
            <button onclick="setPenSize(2)">Small (2px)</button>
            <button onclick="setPenSize(5)">Medium (5px)</button>
            <button onclick="setPenSize(10)">Large (10px)</button>
        </div>
       <div id="grid-container">
            <canvas id="grid">
                <p>Your browser does not support HTML5 canvas</p>
            </canvas>
        </div>
        
        <script>
        // TODO ADD code to initialize canvas and support drawing
        </script>
    </body>
</html>

In the previous tutorial, we were clearing the canvas on resizing, we will no longer do that. Instead, this will now be done by the Clear Canvas method. The following is the modified version of the code required to support the new functionality of the canvas.

// Canvas and drawing context
let gridCanvas, ctx;

// State variables
let mouseDown = false;
let mouseButton = 0;
let penColor = "rgb(0, 0, 0)";
let penWeight = 5;

// Initialize the canvas and its size
function initializeCanvas() {
  // Get the canvas and context
  gridCanvas = document.getElementById("grid");
  ctx = gridCanvas.getContext("2d");

  // Set canvas size to leave room for the buttons
  const viewWidth = window.innerWidth * 0.9;
  const viewHeight = window.innerHeight * 0.7;

  gridCanvas.width = viewWidth;
  gridCanvas.height = viewHeight;

  // Clear and fill the canvas with a white background
  ctx.clearRect(0, 0, viewWidth, viewHeight);
  ctx.fillStyle = "rgb(255,255,255)";
  ctx.fillRect(0, 0, viewWidth, viewHeight);

  // Reattach mouse handlers after reinitialization
  setupMouseHandlers();
}

// Mouse event handlers for drawing on the canvas
function setupMouseHandlers() {
  // Get canvas position offsets
  const rect = gridCanvas.getBoundingClientRect();
  const xOffset = rect.left + window.scrollX;
  const yOffset = rect.top + window.scrollY;

  // Mouse down event
  gridCanvas.onmousedown = (e) => {
    mouseDown = true;
    mouseButton = e.button;
  };

  // Mouse up event
  gridCanvas.onmouseup = () => {
    mouseDown = false;
  };

  // Mouse move event
  gridCanvas.onmousemove = (e) => {
    if (mouseDown) {
      const x = Math.floor((e.pageX - xOffset) / penWeight);
      const y = Math.floor((e.pageY - yOffset) / penWeight);

      ctx.fillStyle = penColor;
      ctx.fillRect(x * penWeight, y * penWeight, penWeight, penWeight);
    }
  };
}

// Functions to set pen properties
function setPenColor(color) {
  penColor = color;
}

function setPenSize(size) {
  penWeight = size;
}

// Initialize canvas on page load
window.onload = initializeCanvas;

So now we have a more useful drawing application that gives that provides some expected functionality. Next week we will tackle the ability to allow custom color selection for the pen and the ability to erase parts of the canvas without clearing the entire area. You can play with this version here.