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>
<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.