Hostingheaderbarlogoj
Join InMotion Hosting for $3.49/mo & get a year on Tuts+ FREE (worth $180). Start today.
Advertisement

How to Create a Web-Based Drawing Application Using Canvas

by
Gift

Want a free year on Tuts+ (worth $180)? Start an InMotion Hosting plan for $3.49/mo.

Combining HTML with the all new <canvas> feature, you can make some pretty awesome web apps! In this tutorial, we will create a neat interactive drawing application using HTML and JavaScript. Along the way, we'll also learn the basic concepts of the all new <canvas> feature.

The <canvas> tag is a relatively new element which is quickly gaining in popularity. It can be used for a variety of different things, such as drawing graphs, shapes, images, applying styles and colors, making photo compositions, and even some simple, neat animations. Today, we'll build a simple online drawing application, similar to http://www.mugtug.com/sketchpad/

Creating a canvas in your site is as simple as adding the <canvas> tag to your HTML document, as shown below:

<canvas id="canvas" width="800" height="600"> 
We're sorry, the browser you are using does not support <canvas>. Please upgrade your browser. 
<!--Anything inside of the canvas tag will only display if the browser does not support the <canvas> tag.--> 
</canvas>

The element 'ID' is not required, but is highly recommended so that you can find it later in your JavaScript and/or CSS.


Step 1 What We're Making

Below is an image of what we will be making. Yours may look a bit different when we are completely finished, depending on the type of styles you wish to use, etc.


As you can see, I am a terrible drawer, but maybe after you are done creating your chalkboard, you can create an awesome masterpiece! Besides, we're building the chalboard, not the drawing!


Step 2 What You'll Need

You'll need a basic understanding of HTML and JavaScript for this tutorial.

  • Photoshop or another image editor
  • Code editor of your choice
  • Basic knowledge of HTML and JavaScript
  • <canvas> supported browser (Chrome, Firefox, Opera, Safari)

I will also be using the free Fugue Icon Pack that can be downloaded here: http://p.yusukekamiyamane.com/

Furthermore, we will be using the following scripts to accomplish the final outcome.


Step 3 Getting Started

Without further ado, let's jump right in!

The HTML Markup

Begin by opening your coding application, and create a regular HTML document. Copy and paste the code below. This is the basic structure of our drawing application. Save the document in a new folder, labeled canvas (or anything you prefer). Now in the same level as your HTML file, create three new folders.

  • JS
  • CSS
  • Images
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
  <html xmlns="http://www.w3.org/1999/xhtml"> 
 
<head> 
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
 
<!-- External CSS Document(s) --> 
  <link rel="stylesheet" type="text/css" href="css/styles.css" /> 
 
<title>Online Drawing Application | Web Design Deluxe</title> 
 
<!-- Eternal JavaScript Document(s) --> 
  <script type="text/javascript" src="js/canvas.js"></script> 
 
</head> 
<body> 
 
<!-- Wrapper Begins -->	<div id="wrapper"> 
 
		<div id="blackboardPlaceholder"> 
		</div> 
 
	</div> 
 
</body> 
</html>

This is the basic markup of our page. Before we begin writing the actual code, let's style this up a bit. I will not be showing you how to make the design in Photoshop, but you can download the images here. Be sure to copy all of the images into the images folder that you just created.

The CSS Markup

Create a new stylesheet named "styles.css," and save it in your "css" folder. Copy and paste the following basic CSS code below to your stylesheet.

@charset "UTF-8"; 
/* CSS Document */ 
 
* { margin:0; padding:0; } 
 
body { 
  background:url(../images/bg.gif) repeat-x #f8f8f8; 
  color:#d7d7d7; 
  font-family:"Belle","Comic Sans MS", cursive; 
  font-size:25px; 
  line-height:27px;} 
 
#wrapper { 
  position:relative; 
  width:960px; 
  margin:0 auto; 
  padding-top:75px;} 
 
<!-- Blackboard --> 
  #blackboardPlaceholder { 
  background:url(../images/blackboard.png) no-repeat; 
  width:924px; 
  height:599px; 
  margin:0 auto; 
  padding:14px 0 75px 14px; 
  cursor:crosshair; 
}

Step 4 The Canvas Tag

We are going to insert the canvas tag right into the blackboardPlaceholder. Place the below code inside the 'blackboardPlaceholder' ID.

<!-- Canvas Begins --> 
<canvas id="drawingCanvas" height="532" width="897"> 
<p class="noscript">We're sorry, this web application is currently not supported with your browser. Please use an alternate browser or download a supported <br />browser. Supported browsers: <a href="http://www.google.com/chrome">Google Chrome</a>, <a href="http://www.opera.com">Opera</a>, <a href="http://www.mozilla.com">Firefox</a>, <a href="http://www.apple.com/safari">Safari</a>, <br />and <a href="http://www.konqueror.org">Konqueror</a>. Also make sure your JavaScript is enabled.</p> 
</canvas> 
<!-- Canvas Ends -->

This is the exact width and height of the canvas we are creating so no need to change that. Also, as I mentioned above, anything in between the canvas tags will be displayed only if JavaScript has been disabled, or the browser does not support canvas.

Next, let's style the ID up a little bit. In your styles.css file, add:

#drawingCanvas { 
 position:absolute; 
 border:none; 
 color:#FFF; 
 overflow:hidden; 
 background-color:transparent; 
 } 
#tempCanvas { position: absolute; width:897px; height:532px; overflow:hidden; }

I will explain the #tempCanvas ID shortly, when we begin writing the JavaScript.


Step 5 JavaScript Implementation

Let's now make our canvas function the way it should. Begin by creating a new JS file, and naming it "canvas". Save this file within the 'JS' folder.

var context;

Next, we will add a function to determine if there is a canvas tag in the HTML document using the addEventListener and onLoad function. Paste this right underneath the variable we created.

// Check for the canvas tag onload. 
   if(window.addEventListener) { 
 window.addEventListener('load', function () {

Now, let's add some default variables and some error messages - if anything went wrong.

var canvas, canvaso, contexto; 
 // Default tool. (chalk, line, rectangle) 
   var tool; 
   var tool_default = 'chalk'; 
 
function init () { 
canvaso = document.getElementById('drawingCanvas'); 
   if (!canvaso) { 
   alert('Error! The canvas element was not found!'); 
   return; 
   } 
 if (!canvaso.getContext) { 
   alert('Error! No canvas.getContext!'); 
   return; 
   } 
// Create 2d canvas. 
   contexto = canvaso.getContext('2d'); 
   if (!contexto) { 
   alert('Error! Failed to getContext!'); 
   return; 
   } 
 // Build the temporary canvas. 
   var container = canvaso.parentNode; 
   canvas = document.createElement('canvas'); 
   if (!canvas) { 
   alert('Error! Cannot create a new canvas element!'); 
   return; 
   } 
 canvas.id     = 'tempCanvas'; 
   canvas.width  = canvaso.width; 
   canvas.height = canvaso.height; 
   container.appendChild(canvas); 
context = canvas.getContext('2d'); 
   context.strokeStyle = "#FFFFFF";// Default line color. 
   context.lineWidth = 1.0;// Default stroke weight. 
 
   // Fill transparent canvas with dark grey (So we can use the color to erase). 
   context.fillStyle = "#424242"; 
   context.fillRect(0,0,897,532);//Top, Left, Width, Height of canvas.

We've created some new variables and methods that will be used later.

The context.strokeStyle is the color of our stroke. We will make the default '#FFFFFF', which is the hex value for white. Next is the context.lineWidth. This is the stroke of our line. We will leave the default value '1.0'. Now we will make a grey rectangle to use later on when we add the ability to save our image. We'll fill the rectangle with grey or '#424242' and make it the exact size of our canvas.

Continuing on, let's create our drop down menu, where we can select between chalk, a rectangle, or a line.

// Create a select field with our tools. 
 var tool_select = document.getElementById('selector'); 
 if (!tool_select) { 
 alert('Error! Failed to get the select element!'); 
 return; 
 } 
 tool_select.addEventListener('change', ev_tool_change, false); 
 
 // Activate the default tool (chalk). 
 if (tools[tool_default]) { 
 tool = new tools[tool_default](); 
 tool_select.value = tool_default; 
 } 
 // Event Listeners. 
   canvas.addEventListener('mousedown', ev_canvas, false); 
   canvas.addEventListener('mousemove', ev_canvas, false); 
   canvas.addEventListener('mouseup',   ev_canvas, false); 
   } 
// Get the mouse position. 
   function ev_canvas (ev) { 
   if (ev.layerX || ev.layerX == 0) { // Firefox 
   ev._x = ev.layerX; 
   ev._y = ev.layerY; 
   } else if (ev.offsetX || ev.offsetX == 0) { // Opera 
   ev._x = ev.offsetX; 
   ev._y = ev.offsetY; 
   } 
// Get the tool's event handler. 
   var func = tool[ev.type]; 
   if (func) { 
   func(ev); 
   } 
   } 
   function ev_tool_change (ev) { 
   if (tools[this.value]) { 
   tool = new tools[this.value](); 
   } 
   } 
// Create the temporary canvas on top of the canvas, which is cleared each time the user draws. 
   function img_update () { 
   contexto.drawImage(canvas, 0, 0); 
   context.clearRect(0, 0, canvas.width, canvas.height); 
   } 
   var tools = {}; 
 // Chalk tool. 
   tools.chalk = function () { 
   var tool = this; 
   this.started = false; 
 // Begin drawing with the chalk tool. 
   this.mousedown = function (ev) { 
   context.beginPath(); 
   context.moveTo(ev._x, ev._y); 
   tool.started = true; 
   }; 
   this.mousemove = function (ev) { 
   if (tool.started) { 
   context.lineTo(ev._x, ev._y); 
   context.stroke(); 
   } 
   }; 
   this.mouseup = function (ev) { 
   if (tool.started) { 
   tool.mousemove(ev); 
   tool.started = false; 
   img_update(); 
   } 
   }; 
   };

We've just made the drawing function for the chalk! Obviously our canvas still won't work at this stage but we're almost there!

Let's make our rectangle tool now.

// The rectangle tool. 
 tools.rect = function () { 
 var tool = this; 
 this.started = false; 
 this.mousedown = function (ev) { 
 tool.started = true; 
 tool.x0 = ev._x; 
 tool.y0 = ev._y; 
 }; 
 this.mousemove = function (ev) { 
 if (!tool.started) { 
 return; 
 } 
 // This creates a rectangle on the canvas. 
 var x = Math.min(ev._x,  tool.x0), 
 y = Math.min(ev._y,  tool.y0), 
 w = Math.abs(ev._x - tool.x0), 
 h = Math.abs(ev._y - tool.y0); 
 context.clearRect(0, 0, canvas.width, canvas.height);// Clears the rectangle onload. 
 
if (!w || !h) { 
   return; 
   } 
   context.strokeRect(x, y, w, h); 
   }; 
   // Now when you select the rectangle tool, you can draw rectangles. 
   this.mouseup = function (ev) { 
   if (tool.started) { 
   tool.mousemove(ev); 
   tool.started = false; 
   img_update(); 
} 
}; 
};

And now for the line tool.

// The line tool. 
 tools.line = function () { 
 var tool = this; 
 this.started = false; 
 this.mousedown = function (ev) { 
 tool.started = true; 
 tool.x0 = ev._x; 
 tool.y0 = ev._y; 
 }; 
 this.mousemove = function (ev) { 
 if (!tool.started) { 
 return; 
 } 
 context.clearRect(0, 0, canvas.width, canvas.height); 
 // Begin the line. 
 context.beginPath(); 
 context.moveTo(tool.x0, tool.y0); 
 context.lineTo(ev._x,   ev._y); 
 context.stroke(); 
 context.closePath(); 
 }; 
 // Now you can draw lines when the line tool is seletcted. 
 this.mouseup = function (ev) { 
 if (tool.started) { 
 tool.mousemove(ev); 
 tool.started = false; 
 img_update(); 
 } 
 }; 
 };

And that just about wraps up our JavaScript! Now let's close the function and variables we created a while back by ending with this:

 init();
}, false); }

Step 6 Inserting The Tool Selection


Let's go back to our HTML page. We will now create the tool selection using a basic HTML dropdown form tag.

Directly below the start of the 'blackboardPlaceholder' tag and right before our canvas tag, add the code below to create the dropdown tool selection.

<p><!-- Tool Selector --> 
<select name="selector" id="selector"> 
<option value="chalk">Chalk</option> 
<option value="line">Line</option> 
<option value="rect">Rectangle</option> 
</select> 
</p>

And that's it! Now we have a drop down form, let's add some styling to it.

.noscript { padding:50px 30px 0 40px; width:820px; } 
#selector { 
 position:absolute; 
 z-index:99999; 
 margin-top:-30px; 
 } 
select { 
 font-family:Verdana, Geneva, sans-serif; 
 font-size:12px; 
 background-color:#EAEAEA; 
 }

The .noscript is the style for the text in between the canvas tag that we never added above.


Step 7 Changing The Color


Just to inform you, those are chalk pieces. I felt that due to my design skills, I had to inform you what they were because many people were telling me how they don't look remotely close to a piece of chalk :)

It's actually quite easy to change the color in the HTML. All you need to do is use the onclick function. Links, images, text, classes, etc. The function we use to change the color is below.

onclick="context.strokeStyle = '#ff00d2';"

To change the color, just change the hex color code in between the parentheses. #FF00D2, used above, will change the stroke color to pink.

Now let's add the HTML markup for the chalk pieces.

<!-- Chalk Pieces --> 
<div id="whiteChalk_button"> 
<img src="images/white.png" width="71" height="17" onclick="context.strokeStyle = '#FFFFFF';" /> 
</div> 
<div id="redChalk_button"> 
<img src="images/red.png" width="71" height="17" onclick="context.strokeStyle = '#F00000';" /> 
</div> 
<div id="orangeChalk_button"> 
<img src="images/orange.png" width="71" height="17" onclick="context.strokeStyle = '#ff9600';" /> 
</div> 
<div id="yellowChalk_button"> 
<img src="images/yellow.png" width="71" height="17" onclick="context.strokeStyle = '#fff600';" /> 
</div> 
<div id="greenChalk_button"> 
<img src="images/green.png" width="71" height="17" onclick="context.strokeStyle = '#48ff00';" /> 
</div> 
<div id="blueChalk_button"> 
<img src="images/blue.png" width="71" height="17" onclick="context.strokeStyle = '#001eff';" /> 
</div> 
<div id="pinkChalk_button"> 
<img src="images/pink.png" width="71" height="17" onclick="context.strokeStyle = '#ff00d2';" /> 
</div>

Add the above code right underneath the </canvas> tag.

Your HTML code should look like the following thus far.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml">  
 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
<!-- External CSS Document(s) --> 
<link rel="stylesheet" type="text/css" href="css/styles.css" /> 
<title>Online Drawing Application | Web Design Deluxe</title> 
<!-- Eternal JavaScript Document(s) --> 
<script type="text/javascript" src="js/canvas.js"></script> 
</head> 
<body> 
 
<!-- Wrapper Begins --> 
<div id="wrapper"> 
 
<div id="blackboardPlaceholder"> 
 
<p><!-- Tool Selector --><select name="selector" id="selector"><option value="chalk">Chalk</option><option value="line">Line</option><option value="rect">Rectangle</option></select></p> 
 
<!-- Canvas Begins --><canvas id="drawingCanvas" height="532" width="897"> <p class="noscript">We're sorry, this web application is currently not supported with your browser. Please use an alternate browser or download a supported <br />browser. Supported browsers: <a href="http://www.google.com/chrome">Google Chrome</a>, <a href="http://www.opera.com">Opera</a>, <a href="http://www.mozilla.com">Firefox</a>, <a href="http://www.apple.com/safari">Safari</a>, <br />and <a href="http://www.konqueror.org">Konqueror</a>. Also make sure your JavaScript is enabled.</p></canvas> <!-- Canvas Ends --> 
 
<!-- Chalk Pieces --><div id="whiteChalk_button"><img src="images/white.png" width="71" height="17" onclick="context.strokeStyle = '#FFFFFF';" /></div>     
 
<div id="redChalk_button"><img src="images/red.png" width="71" height="17" onclick="context.strokeStyle = '#F00000';" /> 
</div> 
 
<div id="orangeChalk_button"><img src="images/orange.png" width="71" height="17" onclick="context.strokeStyle = '#ff9600';" /> 
</div> 
<div id="yellowChalk_button"><img src="images/yellow.png" width="71" height="17" onclick="context.strokeStyle = '#fff600';" /></div> 
 
<div id="greenChalk_button"> 
<img src="images/green.png" width="71" height="17" onclick="context.strokeStyle = '#48ff00';" /></div> 
 
<div id="blueChalk_button"><img src="images/blue.png" width="71" height="17" onclick="context.strokeStyle = '#001eff';" /></div> 
<div id="pinkChalk_button"><img src="images/pink.png" width="71" height="17" onclick="context.strokeStyle = '#ff00d2';" /></div> 
 
</div> 
</div> 
</body> 
</html>

Step 8 Adding An Eraser


The eraser is simply an image that has the same stroke color as the rectangle we created in the JavaScript, '#424242'. Copy and paste the HTML below the chalk pieces we just created above.

<!-- Eraser --> 
<div id="eraser" onclick="context.strokeStyle = '#424242'; context.lineWidth = '22';"></div>

Step 9 Styling The Chalk And Eraser

Now let's add some styling to the chalk pieces and eraser before we moev any further. Add the following to your styles.css file.

#redChalk_button { cursor:pointer; position:absolute; z-index:99999; top:620px; left:160px; } 
#greenChalk_button { cursor:pointer; position:absolute; z-index:99999; top:620px; left:400px; } 
#blueChalk_button { cursor:pointer; position:absolute; z-index:99999; top:620px; left:480px; } 
#yellowChalk_button { cursor:pointer; position:absolute; z-index:99999; top:620px; left:320px; } 
#orangeChalk_button { cursor:pointer; position:absolute; z-index:99999; top:620px; left:240px; } 
#pinkChalk_button { cursor:pointer; position:absolute; z-index:99999; top:620px; left:560px; } 
#whiteChalk_button { cursor:pointer; position:absolute; z-index:99999; top:620px; left:80px; } 
#eraser { 
 position:absolute; 
 background:url(../images/eraser.png) no-repeat; 
 left: 737px; 
 top: 568px; 
 width: 139px; 
 height: 67px; 
 z-index:99999; 
 cursor:pointer; 
 }

Step 10 Changing The Stroke Weight

Changing the stroke is just as easy as changing the color in the HTML. All you have to do is use the 'onclick' function:

onclick="context.lineWidth = '1.0';"

'1.0' is the smallest stroke allowed. You can increase the stroke as much as you want.

Now let's add some stroke features to our HTML. Copy and paste the code below into your HTML document. You will need to place this outside the 'blackboardPlaceholder', immediately following the closing div tag (before the wrapper ends).

<!-- Toggle Stroke Weight --> 
<img src="images/toggle.png" width="16" height="16" id="stroke-subtract" title="Decrease Stroke" onclick="context.lineWidth--;" /> 
<img src="images/toggle-expand.png" width="16" height="16" id="stroke-add" title="Increase Stroke" onclick="context.lineWidth++;" /> 
 
<!-- Stroke Weight Panel --> 
<div id="strokeWeight"> 
<img src="images/stroke1.png" alt="1.0" class="stroke" width="30" height="32" onclick="context.lineWidth = '1.0';" /> 
<img src="images/stroke2.png" alt="6.0" class="stroke" width="30" height="32" onclick="context.lineWidth = '6.0';" /> 
<img src="images/stroke3.png" alt="9.0" class="stroke" width="30" height="32" onclick="context.lineWidth = '9.0';" /> 
<img src="images/stroke4.png" alt="13.0" class="stroke" width="30" height="32" onclick="context.lineWidth = '13.0';" /> 
</div>

Now some CSS:

#stroke-subtract { 
 position:absolute; 
 top:436px; 
 left:-13px; 
 z-index:999999; 
 cursor:pointer; 
 } 
#stroke-add { 
   position:absolute; 
   top:436px; 
   left:5px; 
   z-index:999999; 
   cursor:pointer; 
   } 
#strokeWeight { 
 background:url(../images/stroke-style.png) no-repeat; 
 width:43px; 
 height:153px; 
 position:absolute; 
 top:456px; 
 left:-18px; 
 z-index:1; 
 padding:8px 0 0 7px; 
 } 
.stroke { cursor:pointer; margin-bottom:3px; }

Step 11 The Save Feature


This is probably the most complex section of our tutorial. We'll be using the image/data JavaScript function to save our image. But first, we need an image library. We will use the Canvas2Image and the Base64 Library, created by Jacob Seidelin at nihilogic.dk.

If you haven't already, you can download these files here, and place them in your 'js' folder.

We need to modify the canvas.js file. Add the following to the bottom of your file.

window.onload = function() { 
var bMouseIsDown = false; 
 
   var oCanvas = document.getElementById("drawingCanvas"); 
   var oCtx = oCanvas.getContext("2d"); 
var iWidth = oCanvas.width; 
   var iHeight = oCanvas.height; 
function showDownloadText() { 
   document.getElementById("textdownload").style.display = "block"; 
   } 
function hideDownloadText() { 
   document.getElementById("textdownload").style.display = "none"; 
   } 
function convertCanvas(strType) { 
   if (strType == "PNG") 
   var oImg = Canvas2Image.saveAsPNG(oCanvas, true); 
   if (strType == "BMP") 
   var oImg = Canvas2Image.saveAsBMP(oCanvas, true); 
   if (strType == "JPEG") 
   var oImg = Canvas2Image.saveAsJPEG(oCanvas, true); 
 if (!oImg) { 
   alert("Sorry, this browser is not capable of saving." + strType + " files!"); 
   return false; 
   } 
oImg.id = "canvasimage"; 
 oImg.style.border = oCanvas.style.border; 
   oCanvas.parentNode.replaceChild(oImg, oCanvas); 
howDownloadText(); 
   } 
function saveCanvas(pCanvas, strType) { 
   var bRes = false; 
   if (strType == "PNG") 
   bRes = Canvas2Image.saveAsPNG(oCanvas); 
   if (strType == "BMP") 
   bRes = Canvas2Image.saveAsBMP(oCanvas); 
   if (strType == "JPEG") 
   bRes = Canvas2Image.saveAsJPEG(oCanvas); 
if (!bRes) { 
   alert("Sorry, this browser is not capable of saving " + strType + " files!"); 
   return false; 
   } 
   } 
document.getElementById("convertpngbtn").onclick = function() { 
   convertCanvas("PNG"); 
   } 
document.getElementById("resetbtn").onclick = function() { 
   var oImg = document.getElementById("canvasimage"); 
   oImg.parentNode.replaceChild(oCanvas, oImg); 
 hideDownloadText(); 
   }}

Essentially, when you click the save button, it will convert your canvas into a PNG, and from there, you will be able to right click and download the image. Pretty neat, right!?

Now let's add the HTML:

<!-- Save Image --> 
<div id="saveWrapper"> 
<div id="save"> 
<img src="images/save.png" alt="Save Image" width="16" height="16" id="convertpngbtn" title="Save Image" /> 
</div> 
<div id="textdownload"> 
 Right click the image to download. 
 <img src="images/cross.png" alt="Cancel" width="16" height="16" id="resetbtn" title="Continue Drawing" /> 
</div> 
</div>

Add the above code directly after the wrapper; this will create the save and clear buttons. Now we will add the CSS to style it up a bit.

#saveWrapper { position:absolute; right:0px; } 
#convertpngbtn { 
   float:right; 
   margin-right:40px; 
   margin-top:-10px; 
   position:relative; 
   z-index:9999; 
   cursor:pointer; 
   overflow:hidden; 
   } 
#textdownload { 
 display:none; 
 position:absolute; 
 font-family:Verdana, Geneva, sans-serif; 
 color:#000; 
 font-size:10px; 
 float:right; 
 margin-top:-10px; 
 right:91px; 
 width:250px; 
 overflow:hidden; 
 }

Simply add this code to the styles.css stylesheet.


Step 12 The Advanced Color Table


To add more flexibility, we should create a color table, similar to the one used in Dreamweaver CS4.


So to do this I figured it would be actually quite easy. I would save the above color table, and then use it as a background image of a div id, and then inside, have a seperate div class for each color with the same onclick function we used above. I soon realized that this was not the best solution as it would create a mess in the HTML and would take forever to load each div. So instead I cam up with a new solution that soley consists of JavaScript. I would create each div dynamically in my JavaScript file, and insert the color code for each 'color box' in an array. So before I explain any further, we will do just that. Open your JavaScript file we have been working on, and at the very top of the file right underneath are context variable, create a new variable named "colorPalette". Then we will begin the array. Each new line of colorsI seperated with one line of whitespace in the JavaScript. There are twelve columns total so we will have a total of twelve sections in our array.

Here is the JavaScript:

 var colorPalette = [ //Begin array of color table hex color codes. 
 
"#000000","#000000","#000000","#000000","#003300","#006600","#009900","#00CC00","#00FF00","#330000","#333300","#336600","#339900","#33CC00","#33FF00","#660000","#663300","#666600","#669900","#66CC00","#66FF00", 
 
"#000000","#333333","#000000","#000033","#003333","#006633","#009933","#00CC33","#00FF33","#330033","#333333","#336633","#339933","#33CC33","#33FF33","#660033","#663333","#666633","#669933","#66CC33","#66FF33", 
 
"#000000","#666666","#000000","#000066","#003366","#006666","#009966","#00CC66","#00FF66","#330066","#333366","#336666","#339966","#33CC66","#33FF66","#660066","#663366","#666666","#669966","#66CC66","#66FF66", 
 
"#000000","#999999","#000000","#000099","#003399","#006699","#009999","#00CC99","#00FF99","#330099","#333399","#336699","#339999","#33CC99","#33FF99","#660099","#663399","#666699","#669999","#66CC99","#66FF99", 
 
"#000000","#CCCCCC","#000000","#0000CC","#0033CC","#0066CC","#0099CC","#00CCCC","#00FFCC","#3300CC","#3333CC","#3366CC","#3399CC","#33CCCC","#33FFCC","#6600CC","#6633CC","#6666CC","#6699CC","#66CCCC","#66FFCC", 
 
"#000000","#FFFFFF","#000000","#0000FF","#0033FF","#0066FF","#0099FF","#00CCFF","#00FFFF","#3300FF","#3333FF","#3366FF","#3399FF","#33CCFF","#33FFFF","#6600FF","#6633FF","#6666FF","#6699FF","#66CCFF","#66FFFF", 
 
"#000000","#FF0000","#000000","#990000","#993300","#996600","#999900","#99CC00","#99FF00","#CC0000","#CC3300","#CC6600","#CC9900","#CCCC00","#CCFF00","#FF0000","#FF3300","#FF6600","#FF9900","#FFCC00","#FFFF00", 
 
"#000000","#00FF00","#000000","#990033","#993333","#996633","#999933","#99CC33","#99FF33","#CC0033","#CC3333","#CC6633","#CC9933","#CCCC33","#CCFF33","#FF0033","#FF3333","#FF6633","#FF9933","#FFCC33","#FFFF33", 
 
"#000000","#0000FF","#000000","#990066","#993366","#996666","#999966","#99CC66","#99FF66","#CC0066","#CC3366","#CC6666","#CC9966","#CCCC66","#CCFF66","#FF0066","#FF3366","#FF6666","#FF9966","#FFCC66","#FFFF66", 
 
"#000000","#FFFF00","#000000","#990099","#993399","#996699","#999999","#99CC99","#99FF99","#CC0099","#CC3399","#CC6699","#CC9999","#CCCC99","#CCFF99","#FF0099","#FF3399","#FF6699","#FF9999","#FFCC99","#FFFF99", 
 
"#000000","#00FFFF","#000000","#9900CC","#9933CC","#9966CC","#9999CC","#99CCCC","#99FFCC","#CC00CC","#CC33CC","#CC66CC","#CC99CC","#CCCCCC","#CCFFCC","#FF00CC","#FF33CC","#FF66CC","#FF99CC","#FFCCCC","#FFFFCC", 
 
"#000000","#FF00FF","#000000","#9900FF","#9933FF","#9966FF","#9999FF","#99CCFF","#99FFFF","#CC00FF","#CC33FF","#CC66FF","#CC99FF","#CCCCFF","#CCFFFF","#FF00FF","#FF33FF","#FF66FF","#FF99FF","#FFCCFF","#FFFFFF" 
 
];

And that's every color in our color table. Now let's add the JavaScript to make it work.

$(document).ready(function() { 
 // Handles showing/hiding the color table 
   $("#colorTable").hide(); 
 
   $("#color").click(function() { 
   $("#colorTable").show(); 
   }); 
   $(document).click(function() { 
   $("#colorTable").hide(); 
   }); 
   $("#color").click(function(event) { 
   event.stopPropagation(); 
   }); 
   }); 
function LoadColorTable() { // Populate the color picker table with colors specified in the 'colorPalette' array 
   for (i = 0; i < colorPalette.length; i++) { 
   var colorDiv = document.createElement("div"); 
   colorDiv.className = "color"; 
   colorDiv.id = "colorSwatch" + i; 
   colorDiv.style.backgroundColor = colorPalette[i]; 
   colorDiv.setAttribute("onclick", "SetColor(id);"); 
   document.getElementById("colorTable").appendChild(colorDiv); 
   }; 
   } 
function SetColor(id) { // Set the color of the drawing tool when a color swatch is clicked 
   context.strokeStyle = document.getElementById(id).style.backgroundColor; 
   }

Okay, so the code above, we start by adding some functions to show or hide the colorTable ID in our HTML (which we will get to in a moment). This is just basic jquery for when you click the colorTable or anywhere outside the colorTable it will hide the ID. Now we will load the colorTable. Do do this we will populate it with all of the color codes we added in the 'colorPalette' array. And finally to make everything work, we will set the color of the drawing tool when a color swatch is clicked. To do this, we will simply make each color a class of 'color' and then use the array to make each hex color value the background. And finally use a function so when a color is clicked, the context.strokeStyle will equal the background image.

And for the HTML markup, you will add the following code immediately after the wrapper is started in your HTML.

<!-- Color Table (controlled in JavaScript) --> 
<div id="colorTable"></div> 
<!-- Toggle Color Button --> 
<div id="color" title="Toggle Color"> 
<img src="images/color-arrow.png" alt="Toggle Color" width="16" height="16" /> 
</div>

And now let's add some style to our color table.

#colorTable { 
 width:231px; 
 height:132px; 
 position:absolute; 
 margin-top:8px; 
 z-index:999999; 
 right:80px; 
 background-color: #000000; 
 display:none; 
 cursor:pointer; 
 } 
.color { 
   position:relative; 
   height:7px; 
   width:7px; 
   float:left; 
   padding:1px; 
   margin:1px; 
   } 
.color:hover{ border:solid 1px #FFF; margin:0px; }

Add this anywhere into your styles.css file you created a while back.

And there you have it! Now we have over 200 different colors that we can choose from!


Step 13 Using the Reload Function to Clear the Canvas

Now we will create a simple button to clear the canvas. The easiest way to do this is simply refresh the page. So we are going to use a function I am sure you are all familiar with. If not, the below code will simply refresh the page using JavaScript.

<a href="javascript:location.reload(true)">Clear</a>

That's it. So now let's add it into our HTML. We will use the image in your 'images' folder that looks like the radioactive symbol. I'm not sure why I used a radioactive symbol for this, but I couldn't find any other icon in the icon pack to use, so this will suffice.

Add the following image to you HTML below. Because it has an absolute position it really doesn't matter where you place it as long as place it outside of the 'blackboardPlaceholder' and within the 'wrapper'. So just to make the code look "in order" we are going to place the following code right after our ID "color".

<!-- Clear Canvas Button --> 
<div id="nuke" title="Clear Canvas"> 
<a href="javascript:location.reload(true)"> 
<img src="images/burn.png" alt="Clear Canvas" width="16" height="16" /> 
</a> 
</div>

And of course, some CSS:

#nuke { position:absolute; cursor:pointer; margin-top:-10px; right:100px; }

And there you have it. A nice looking 'clear' button.


Step 14 Adding an Extra Feature to the Stroke Menu


After I completed this drawing application I still felt that the weight of the strokes you were able to choose were still a bit low. So I though I would make a new little function for that. I will not remove the stroke menu we already currently have, I will simply add on to it a bit. My idea was to have a plus and a minus button. The plus button would increase the stroke weight by one, and the minus button would obviously decrease the stroke by one.

So in order to do this we will find some nice plus and minus buttons in our icon pack to use. We will then write the HTML write above the ID 'storkeWeight'.

<!-- Toggle Stroke Weight --> 
<img src="images/toggle.png" width="16" height="16" id="stroke-subtract" title="Decrease Stroke" onclick="context.lineWidth--;" /> 
<img src="images/toggle-expand.png" width="16" height="16" id="stroke-add" title="Increase Stroke" onclick="context.lineWidth++;" />

The onclick function is a bit different than what we used before, basically the '--' and the '++' values will simply add or subtract 1 from the default value. The default value is 1.0 so when you click the plus button, the stroke will now be 2.0, a bit bigger than the default.

And now the CSS:

#stroke-subtract { 
 position:absolute; 
 top:436px; 
 left:-13px; 
 z-index:999999; 
 cursor:pointer; 
 } 
#stroke-add { 
   position:absolute; 
   top:436px; 
   left:5px; 
   z-index:999999; 
   cursor:pointer; 
   }

Step 15 Adding Tooltips


In order to make are application more user-friendly we will need to add some titles to all of our buttons. Luckily I have already included all of the code in the HTML, you just didn't notice it. Basically all of our icons in the HTML code have the title tag. You all should know what title tags are, but we are going to use those tags to implement a rather nice jQuery tooltip effect known as Tipsy. I have used Tipsy many times in other projects and it is really a great plugin. You will need to download the Tipsy files here. Place the 'tipsy.css' file in your css folder, the 'jquery.tipsy.js' in your js folder, and the 'tipsy.gif' in your images folder if it is not there already.

You will need to add the jQuery library to your header. Here is the direct link to the latest jQuery library. You can link directly to this or download it to your 'js' folder:

http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js

Now we will need to call the JavaScript file for tipsy. Make sure when you call this in your header, the jQuery script comes before this script. It should like like this:

<script type="text/javascript" src="js/jquery.tipsy.js"></script>

And then call the 'tipsy.css' file in your HTML. That should look like the following:

<link rel="stylesheet" type="text/css" href="css/tipsy.css" />

And now let's call the actually JavaScript. Place this in your header below all of the external JavaScript and CSS sources.

<script type='text/javascript'> 
 $(function() { 
 $('#nuke').tipsy({gravity: 's'}); 
 $('#color').tipsy({gravity: 's'}); 
 $('#convertpngbtn').tipsy({gravity: 's'}); 
 $('#resetbtn').tipsy({gravity: 's'}); 
 $('#stroke-subtract').tipsy({gravity: 's'}); 
 $('#stroke-add').tipsy({gravity: 's'});  }); 
 </script>

You will also need to add one more thing to your styles.css file to fancy up the tooltips a little bit:

.tooltip{ 
 position: absolute; 
 top: 0; 
 left: 0; 
 z-index: 3; 
 display: none; 
 background-color:#F00; 
 }

Wrapping It Up

And that just about wraps it up! Congratulations. Please do let me know if you have any questions or thoughts on ways to improve this application. Thanks for reading!

Advertisement