Paint App

Paint app using javascript in HTML 5 canvas

            HTML 5 provides a canvas element using which we can draw shapes on it,colour it etc.
So this is a simple paint app i created using javascript in canvas which provides tools like pencil,line,rectangle,circle,spray,brush etc.

This is how my app looks like in chrome browser.


























Canvas element in html 5 provides the drawing surface.More about canvas can be read from Dive into html 5 book.
The following is an example of canvas declaration.
 <canvas id="canvas" width="650" height="450" style="border:5px solid black; background-color:white;">  
 </canvas>  

Inside the script we have to initialize two variables.
1:  var canvas = document.getElementById("canvas");  
2:  var context=canvas.getContext('2d');  

We have to initialize a variable to access canvas using canvas id and another variable to set the context to 2 dimension as above.

No temporary canvas is used in this app.Instead i used the getImageData() function which captures the canvas as a whole ( ofcourse we have to specify the start and ending points correctly) and used putImageData() to update the canvas with the captured image.

Pencil tool

Pencil tool is implemented by using the basics of line draw in canvas.On a mouse press it will track its movement and on mouse move we will update the x,y coordinates.Also we will draw a small line from previous tracked x,y coordinte to updated x,y coordinate.
Here is the code.
1:  function pencil(){  
2:  canvas.onmousedown=pencildown;  
3:  canvas.onmouseup=pencilup;  
4:  canvas.onmousemove=pencilmove;  
5:  function pencildown(e){  
6:  x=e.x;  
7:  y=e.y;  
8:  draw=true;  
9:  }  
10:  function pencilup(){  
11:  draw=false;  
12:  }  
13:  function pencilmove(event){  
14:  if (draw){  
15:    a =event.x;  
16:    b =event.y;  
17:    context.beginPath();  
18:    context.moveTo(x,y);  
19:    context.lineTo(a,b);  
20:    context.stroke();  
21:    context.closePath();  
22:    x=a;  
23:    y=b;  
24:   }}}  

Line tool

Line tool can be easily implemented.The hard work lies in handling the mouse events.Here on mouse down(or press) we store the starting points to a variable.On mouse move we update the end points of the line using the coordinates from the mouse move  event.
I used the getImageData() on mouse down event.That is, on mouse down event it will take the image of the canvas.And on mouse move it will update the canvas background with that image.
1:  function line(){  
2:  canvas.onmousedown=linedown;  
3:  canvas.onmouseup=lineup;  
4:  canvas.onmousemove=linemove;  
5:  function linedown(e){  
6:   img=context.getImageData(0,0,canvas.width,canvas.height);  
7:   startx=e.x;  
8:   starty=e.y;  
9:   drag1=true;  
10:  }  
11:  function lineup(e){  
12:   drag1=false;  
13:  }  
14:  function linemove(e){  
15:   if (drag1){  
16:   context.putImageData(img,0,0);  
17:   endx=e.x;  
18:   endy=e.y;  
19:   context.beginPath();  
20:   context.moveTo(startx,starty);  
21:   context.lineTo(endx,endy);  
22:   context.stroke();  
23:   context.closePath();  
24:  }}}  


Rectangle tool

Two types of rectangle are there for canvas.Stroke and Fill.So i provide radio buttons to select the type of rectangle(or Circle) we want.If radio button of Fill is checked value of variable fill become 1 and if Border is checked fill value become zero.
Here is the code
1:  function rectangle(){  
2:  canvas.onmousedown=rectdown;  
3:  canvas.onmouseup=rectup;  
4:  canvas.onmousemove=rectmove;  
5:  function rectdown(e){  
6:   img=context.getImageData(0,0,canvas.width,canvas.height);  
7:   startx=e.x;  
8:   starty=e.y;  
9:   drag2=true;  
10:  }  
11:  function rectup(e){  
12:  drag2=false;  
13:  }  
14:  function rectmove(e){  
15:  if (drag2){  
16:  context.putImageData(img,0,0);  
17:  rectw=e.x-startx;  
18:  recth=e.y-starty;  
19:  context.strokeRect(startx,starty,rectw,recth);  
20:  if (f==1){  
21:  context.fillRect(startx,starty,rectw,recth);  
22:  }  
23:  }}}  

Here on mouse press it will store the x,y coordinates as starting point of rectangle.On mouse move event it updates the height and width of the rectangle until mouse up event is performed.If the fill variable is "1" it will overwrite strokeRect with fillRect.

Circle tool

There is no direct function in canvas to draw circle like fillRect or strokeRect.But we can draw arc.So we will extend the arc to a circle by giving starting angle as zero and ending angle as square of 3.14(pi value).

 context.arc(centerx,centery,radius, 0, Math.PI*2, true);  

0 notates starting angle and Math.PI*2 notates ending angle.
Here is how the function circle looks like,
1:  function circle(){  
2:  canvas.onmousedown=circledown;  
3:  canvas.onmouseup=circleup;  
4:  canvas.onmousemove=circlemove;  
5:  function circledown(e){  
6:   img=context.getImageData(0,0,canvas.width,canvas.height);  
7:   startx=e.x;  
8:   starty=e.y;  
9:   drag3=true;  
10:  }  
11:  function circleup(e){  
12:  drag3=false;  
13:  }  
14:  function circlemove(e){  
15:  if (drag3){  
16:  context.putImageData(img,0,0);  
17:  endx=e.x;  
18:  endy=e.y;  
19:  context.beginPath();  
20:  context.arc((endx+startx)/2,(endy+starty)/2,Math.sqrt(Math.pow(endx-startx,2)+Math.pow(endy-starty,2))/2, 0, Math.PI*2, true);   
21:  context.closePath();  
22:  context.stroke();  
23:  if (f==1){  
24:  context.fill();  
25:  }  
26:  }}}  


Even though the arc coordinates look complex,its actually the javascript representation for length equation of line when end points are given.

Eraser

For a eraser tool we use the clearRect function in canvas.ClearRect function clears the pixels in the specified rectangle.
 context.clearRect(10,10,20,20)  

The code above will clear pixels on rectangle that has starting points from 10,10 having a width of 20 and height of 20.
Eraser function is as given below.
1:  function erase(){  
2:  canvas.onmousedown=erasedown;  
3:  canvas.onmouseup=eraseup;  
4:  canvas.onmousemove=erasemove;  
5:  function erasedown(e){  
6:   drag5=true;  
7:  }  
8:  function eraseup(e){  
9:  drag5=false;  
10:  }  
11:  function erasemove(e){  
12:  if(drag5){  
13:  x=e.x;  
14:  y=e.y;  
15:  context.clearRect(x,y,20,20);  
16:  }}}  

On mouse down it will update clearRect  with x,y coordinates recieved from each mouse move event and clears pixels in that area of rectangle.


Spray

Spray function is just the mixing of little rectangles and squares near to the coordinates obtained from mouse events.

1:  function spray(){  
2:  canvas.onmousedown=spraydown;  
3:  canvas.onmouseup=sprayup;  
4:  canvas.onmousemove=spraymove;  
5:  function spraydown(e){  
6:  x=e.x;  
7:  y=e.y;  
8:   drag8=true;  
9:  for (var i=0;i<20;i=i+6){  
10:  context.fillRect(x+i,y+i,1.5,1.5);  
11:  context.fillRect(x-i,y-i,1.5,1.5);  
12:  context.fillRect(x-i,y+i,1.5,1.5);  
13:  context.fillRect(x+i,y-i,1.5,1.5);  
14:  context.fillRect(x-i,y,1,1);  
15:  context.fillRect(x,y-i,1,1);  
16:  context.fillRect(x,y+i,1,1);  
17:  context.fillRect(x+i,y,1,1);  
18:  }  
19:  context.beginPath();  
20:  for(var i=0;i<12;i=i+4){  
21:  context.arc(x+i,y+i,1.3, 0, Math.PI*2, true);   
22:  context.arc(x-i,y+i,1.3, 0, Math.PI*2, true);  
23:  context.arc(x+i,y-i,1.3, 0, Math.PI*2, true);  
24:  context.arc(x-i,y-i,1.3, 0, Math.PI*2, true);   
25:  context.arc(x,y-i,1.3, 0, Math.PI*2, true);  
26:  context.arc(x-i,y,1.3, 0, Math.PI*2, true);  
27:  context.arc(x,y+i,1.3, 0, Math.PI*2, true);  
28:  context.arc(x+i,y,1.3, 0, Math.PI*2, true);  
29:  }   
30:  context.closePath();  
31:  context.fill();  
32:  }  
33:  function sprayup(e){  
34:  drag8=false;  
35:  }  
36:  function spraymove(e){  
37:  if (drag8){  
38:  x=e.x;  
39:  y=e.y;  
40:  for (var i=0;i<20;i=i+6){  
41:  context.fillRect(x+i,y+i,1,1);  
42:  context.fillRect(x-i,y-i,1,1);  
43:  context.fillRect(x+i,y-i,1,1);  
44:  context.fillRect(x-i,y+i,1,1);  
45:  context.fillRect(x-i,y,1,1);  
46:  context.fillRect(x,y-i,1,1);  
47:  context.fillRect(x,y+i,1,1);  
48:  context.fillRect(x+i,y,1,1);  
49:  }  
50:  context.beginPath();  
51:  for(var i=0;i<12;i=i+4){  
52:  context.arc(x+i,y+i,1.3, 0, Math.PI*2, true);   
53:  context.arc(x-i,y+i,1.3, 0, Math.PI*2, true);  
54:  context.arc(x+i,y-i,1.3, 0, Math.PI*2, true);  
55:  context.arc(x-i,y-i,1.3, 0, Math.PI*2, true);    
56:  context.arc(x,y-i,1.3, 0, Math.PI*2, true);  
57:  context.arc(x-i,y,1.3, 0, Math.PI*2, true);  
58:  context.arc(x,y+i,1.3, 0, Math.PI*2, true);  
59:  context.arc(x+i,y,1.3, 0, Math.PI*2, true);  
60:  }  
61:  context.closePath();  
62:  context.fill();  
63:  }}  
64:  }  


Here we can see that i created small rectangle and squares around the coordinate obtained from mouse event so that it will give spray effect.

The Brush tool is easy to implement.It can be implemented in many different ways.I used 3 small circles in a line manner at the coordinates obtained from mouse events.

Below given is an image drawn using the Paint App..































See full code from my GitHub...