This is the second post of Drawing on the Web
Welcome back to our canvas drawing adventure! In our last post, we created a basic drawing app that could handle mouse events and let us draw with a black brush. It was functional, but let’s be honest – it had about as much personality as a default Windows screensaver.
Today we’re going to fix that by adding brush size options and color selection. Because what’s the point of digital art if you can’t make it ridiculously colorful?
What We’re Adding Today
We’ll enhance our drawing app with:
- Three brush size options (small, medium, large)
- A color picker to choose any color we want
- Simple UI controls that actually look decent
The best part? We’re still keeping it vanilla JavaScript – no frameworks, no dependencies, just pure web goodness.
Updating Our HTML Structure
First, let’s add some UI elements to our HTML. We’ll add these controls above our canvas:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tiny Drawing App</title>
<style>
body {
margin: 0;
padding: 20px;
font-family: Arial, sans-serif;
background-color: #f0f0f0;
}
.controls {
text-align: center;
margin-bottom: 20px;
padding: 15px;
background-color: white;
border: 2px solid #333;
border-radius: 8px;
display: inline-block;
margin-left: 50%;
transform: translateX(-50%);
}
.control-group {
display: inline-block;
margin: 0 20px;
vertical-align: top;
}
.control-group h3 {
margin: 0 0 10px 0;
font-size: 14px;
color: #333;
}
.brush-sizes {
display: flex;
gap: 10px;
}
.brush-size {
width: 40px;
height: 40px;
border: 2px solid #ccc;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
background-color: white;
}
.brush-size:hover {
border-color: #333;
}
.brush-size.active {
border-color: #007bff;
background-color: #e3f2fd;
}
.brush-preview {
background-color: #333;
border-radius: 50%;
}
#colorPicker {
width: 60px;
height: 40px;
border: 2px solid #333;
border-radius: 8px;
cursor: pointer;
}
#drawingCanvas {
border: 2px solid #333;
cursor: crosshair;
background-color: white;
display: block;
margin: 0 auto;
}
</style>
</head>
<body>
<h1 style="text-align: center;">Tiny Drawing App</h1>
<div class="controls">
<div class="control-group">
<h3>Brush Size</h3>
<div class="brush-sizes">
<div class="brush-size active" data-size="2">
<div class="brush-preview" style="width: 6px; height: 6px;"></div>
</div>
<div class="brush-size" data-size="5">
<div class="brush-preview" style="width: 12px; height: 12px;"></div>
</div>
<div class="brush-size" data-size="10">
<div class="brush-preview" style="width: 20px; height: 20px;"></div>
</div>
</div>
</div>
<div class="control-group">
<h3>Color</h3>
<input type="color" id="colorPicker" value="#000000">
</div>
</div>
<canvas id="drawingCanvas"></canvas>
<script src="script.js"></script>
</body>
</html>
Enhanced JavaScript Functionality
Now let’s update our JavaScript to handle these new controls. We’ll add to our existing code:
// Get the canvas and its 2D context (from previous post)
const canvas = document.getElementById('drawingCanvas');
const ctx = canvas.getContext('2d');
// Set canvas size (from previous post)
canvas.width = 800;
canvas.height = 600;
// Drawing state (from previous post)
let isDrawing = false;
let lastX = 0;
let lastY = 0;
// NEW: Drawing settings
let currentBrushSize = 2;
let currentColor = '#000000';
// Set up the drawing context with our new settings
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.strokeStyle = currentColor;
ctx.lineWidth = currentBrushSize;
// NEW: Get UI elements
const colorPicker = document.getElementById('colorPicker');
const brushSizes = document.querySelectorAll('.brush-size');
// NEW: Color picker event listener
colorPicker.addEventListener('change', (e) => {
currentColor = e.target.value;
ctx.strokeStyle = currentColor;
});
// NEW: Brush size selection
brushSizes.forEach(brushSize => {
brushSize.addEventListener('click', (e) => {
// Remove active class from all brush sizes
brushSizes.forEach(bs => bs.classList.remove('active'));
// Add active class to clicked brush size
e.currentTarget.classList.add('active');
// Update current brush size
currentBrushSize = parseInt(e.currentTarget.dataset.size);
ctx.lineWidth = currentBrushSize;
});
});
// Drawing functions (same as previous post)
function startDrawing(e) {
isDrawing = true;
const rect = canvas.getBoundingClientRect();
lastX = e.clientX - rect.left;
lastY = e.clientY - rect.top;
}
function draw(e) {
if (!isDrawing) return;
const rect = canvas.getBoundingClientRect();
const currentX = e.clientX - rect.left;
const currentY = e.clientY - rect.top;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(currentX, currentY);
ctx.stroke();
lastX = currentX;
lastY = currentY;
}
function stopDrawing() {
isDrawing = false;
}
// Event listeners (same as previous post)
canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
canvas.addEventListener('mouseout', stopDrawing);
Breaking Down the New Features
Brush Size Selection: We created three circular buttons that show a visual preview of each brush size. The data-size attribute stores the actual brush width value, and we use event delegation to handle clicks on all brush size buttons.
Active State Management: When you click a brush size, we remove the ‘active’ class from all buttons and add it to the clicked one. It’s like a radio button group, but fancier!
Color Picker Integration: HTML5’s <input type="color"> gives us a native color picker for free. When the color changes, we update both our currentColor variable and the canvas context’s strokeStyle.
Visual Feedback: The brush size previews actually show you what size brush you’re selecting. It’s a small touch, but it makes the interface much more intuitive.
Why This Design Works
You might notice we’re storing the current brush size and color in variables instead of reading them from the DOM every time we draw. This is a performance optimization – DOM queries are relatively expensive, so it’s better to cache these values and only update them when the user changes the settings.
The CSS is doing some heavy lifting too. Those brush size buttons are perfectly circular thanks to border-radius: 50%, and the hover effects provide nice feedback when users interact with the controls.
Testing Your Enhanced App
Fire up your drawing app and try out the new features:
- Test the brush sizes: Switch between small, medium, and large brushes. Notice how the active state changes?
- Play with colors: Pick some wild colors and create a rainbow masterpiece
- Combine features: Try drawing with a large red brush, then switch to a tiny blue one for details
The app should feel much more responsive and professional now. You’ve got visual feedback, smooth interactions, and the ability to create actual artwork (or at least colorful squiggles).
What’s Coming Next
Our drawing app is looking pretty good, but what happens when you make a mistake? Or when you want to save your masterpiece? In our final post, we’ll add a clear button to wipe the canvas clean and a save function to download your artwork as an image file.
Get ready to turn your browser into a legitimate art studio!
Next up: Clear and Save functionality – because everyone deserves a second chance and the ability to show off their digital doodles!