DEV Community

Cover image for Build a Web Paint Application
Anshika
Anshika

Posted on • Updated on

Build a Web Paint Application

How exciting is it to build something you grew up using?

I'm pretty sure that most of you have used Microsoft Paint. Didn't we all feel like Picasso after drawing a scenery with mountains, a hut, a single tree, and two birds flying? We did!

This project is similar to it, or at least the idea is similar. Even if you're an absolute beginner in web development, you can create this one. This tutorial focuses on building this project and not on HTML, CSS or JavaScript. Neither it is a <canvas> tutorial.

Pre-requisites

  • Basic understanding of HTML & CSS
  • DOM manipulation

What will you be building?

A web application built using HTML5, CSS and JavaScript. This tutorial is created for beginners. You can draw lines, change color & size of stroke, erase & get custom color as well.

Let's dive into it! ⚑

Canvas introduction

HTML5 provides an element <canvas> </canvas> which is used to draw graphics via scripting on a web page. It has a default size of 300px Γ— 150px. We will use JavaScript context object to draw the graphics on our canvas. It can have attributes, id, classes etc.

Think of <canvas> as an actual canvas, JavaScript context object as paints & yourself as an artist 🎨.

Before starting the project, you can go ahead and try it out yourself. Live project

<canvas id="canvas">Fallback text</canvas>
Enter fullscreen mode Exit fullscreen mode

Note: Canvas is supported by following browsers

  • Chrome 102 and 103
  • Firefox 101 and 102
  • Edge 101 and 102
  • Safari 14 and 15

πŸ’» It is finally time to get into the coding part.
To save you some time of creating the UI of application, I've created starter files which you can download here.

Starter Code: GitHub Repo Link

UI of app

Eraser

If you choose your canvas to be of specific color, you can make eraser by creating a brush having same color as that of canvas. This will work, but is not efficient. Purpose of an eraser is to remove the pixels from the specified area/region and that is what we will be doing.
We can use globalCompositeOperation property of Context API to do the intended task.

const erase = () => (ctx.globalCompositeOperation = "destination-out");
Enter fullscreen mode Exit fullscreen mode

Toggle brush size dropdown

function sizeList() {
  document.querySelector(".size-list").classList.toggle("show-list");
}
Enter fullscreen mode Exit fullscreen mode

Set brush size

To set the chosen size as brush size, add event-listener to each size in the list. If the user clicks on any of the specified size, change the value of global variable storing the brush thickness.

Make sure to call the brushSize() function on dropdown of brush size.

function brushSize() {
  var brushSet = document.getElementsByClassName("size");
  Array.prototype.forEach.call(brushSet, function (element) {
    element.addEventListener("click", function () {
      brushthickness = element.getAttribute("style").substr(11, 2);
    });
  });
}
Enter fullscreen mode Exit fullscreen mode

Set Color

When we change the color, it will not be feasible for user to remember the chosen color. That is why it will be a better user experience if we indicate the active color in a box, similar to MS Paint.
This is easy since we only have to change the background of the box and set the value of stroke to global variable storing the active color. We will see how and where we will manipulate this variable.

function setActiveColor() {
  document.querySelector(".color-btn div").style.backgroundColor = color;
  ctx.strokeStyle = color;
  ctx.globalCompositeOperation = "source-over";
}
Enter fullscreen mode Exit fullscreen mode

Color palette
Color palette is created by small blocks in navbar, to select it and set it as stroke color we need to add click event listener to each block. Once a block it clicked, set the global color variable as attribute value of style. Once that is done we can call our setActiveColor() function.

function setColor() {
  var palette = document.getElementsByClassName("color");
  Array.prototype.forEach.call(palette, function (element) {
    element.addEventListener("click", function () {
      color = element.getAttribute("style").split("--set-color:")[1];
      setActiveColor();
    });
  });
}
Enter fullscreen mode Exit fullscreen mode

Under this topic, last thing we need to do is to get the color-picker to work i.e., to get the value at set it to global variable.

function colorPick() {
  color = document.getElementById("color-picker").value;
  setActiveColor();
}
Enter fullscreen mode Exit fullscreen mode

Draw functionality

πŸ₯³The heart of this application is finally here, we will now focus on creating the functionality of drawing the elements on the canvas. Drawing on canvas has dedicated steps to follow:

  • Begin the drawing path.
  • Keep updating the positions of lines when the mouse movement happens.
  • Create the lines from start to end positions.
  • Stoke the path.
function draw(e) {
  if (e.buttons !== 1) return; // if mouse is not clicked, do not go further

  ctx.beginPath(); // begin the drawing path
  ctx.lineWidth = brushthickness; // width of line
  ctx.lineCap = "round"; // rounded end cap
  ctx.strokeStyle = color; // hex color of line
  ctx.moveTo(pos.x, pos.y); // from position
  setPosition(e);
  ctx.lineTo(pos.x, pos.y); // to position
  ctx.closePath();
  ctx.stroke(); // draw it!
}
Enter fullscreen mode Exit fullscreen mode

With this your own web paint application is ready, share it with your friends and have fun!
Foo

Hope you learned something! Keep creating!

Top comments (27)

Collapse
 
michaeltharrington profile image
Michael Tharrington

This is super cool! Nicely done. πŸ™Œ

If you're going to continue the trend of rebuilding old MS tech for the web, I'd like to suggest bringing back Clippy as a browser extension, haha! πŸ˜€

Clippy, aka Microsoft's Office Assistant, raising eyebrows and wiggling around

Collapse
 
anshika_gautam_ profile image
Anshika

Sure, I'll give it a try.

Collapse
 
michaeltharrington profile image
Michael Tharrington

Oh what?! That would be so cool. πŸ™Œ

Maybe it could give writing advice in the DEV editor, haha! Almost like a Grammarly. Or if ya wanted to make it a joke, it could give out bad writing advice, lol.

If you do make a Clippy clone for the browser, whichever direction you take it, I'd be so siked to read about it! πŸ˜€

Collapse
 
anuragprasoon profile image
Anurag Prasoon

Nice Blog , Anshika

Collapse
 
thomasbnt profile image
Thomas Bnt β˜•

Oww so cool ! 🀩

Collapse
 
cicirello profile image
Vincent A. Cicirello

Fun little web application. Very nice.

Collapse
 
naucode profile image
Al - Naucode

Really cool project, good job!

Collapse
 
developerbishwas profile image
Bishwas Bhandari

Looks cool, thanks for sharing.

Collapse
 
coditdoc profile image
Codeitdoc7 • Edited

Now its time to wake up the artist in my friend πŸ˜„.

Thanks @anshika_gautam_ its a great article.

Collapse
 
anshika_gautam_ profile image
Anshika

Haha! Definitely!

Collapse
 
decker67 profile image
decker

Nice one, thank you.

Collapse
 
muhyilmaz profile image
MUHAMMED YILMAZ

easy tutorial. Thanks :)

Collapse
 
acode123 profile image
acode123

It took you a lot of time to create this, thanks.

Collapse
 
anshika_gautam_ profile image
Anshika

What should I write about next?

Collapse
 
coditdoc profile image
Codeitdoc7

How to wake up writer in your friend 😸

Collapse
 
tatrakrad profile image
tatra • Edited

For the curious, everything works as copy pasted except for mouse cursor position

// initialize position as 0,0
var pos = { x: 0, y: 0 };

// new position from mouse events
function setPosition(e) {
  pos.x = parseInt(e.clientX - offsetX);
  pos.y = parseInt(e.clientY - offsetY);
}
Enter fullscreen mode Exit fullscreen mode

or adding event listeners to the document (not window)

document.addEventListener("mousemove", draw);
document.addEventListener("mousedown", setPosition);
document.addEventListener("mouseenter", setPosition);
document.getElementById("color-picker").addEventListener("change", colorPick);
setColor();
Enter fullscreen mode Exit fullscreen mode
Collapse
 
anshika_gautam_ profile image
Anshika

Mouse cursor position has to be manipulated according to your preference and viewport size. You can change the x and y position as per your convenience. And I didn't understand what is not working for you in event listeners. Can you elaborate?

Collapse
 
tatrakrad profile image
tatra • Edited

im just helpfully posting snippets that make the rest of this code work. It's your code by the way, from your finished version

Collapse
 
karna98 profile image
Vedant Wakalkar

Just a suggestion, if the project is deploy-able, then deploy it. People can actually use it and give feedback for the same.

As this is JavaScript Project you can deploy it using GitHub Pages too.

Collapse
 
anshika_gautam_ profile image
Anshika

Hey! :D Project is already deployed and live link is provided in the tutorial itself.

Collapse
 
karna98 profile image
Vedant Wakalkar

Yup found it in the post but missing from GitHub Repository description (That's where I usually look at).

Collapse
 
anshika_gautam_ profile image
Anshika

Great! Thank You for suggestions.

Collapse
 
tatrakrad profile image
tatra

doesn't work, draw never gets called

Collapse
 
anshika_gautam_ profile image
Anshika

Hey, maybe you skipped calling the function.