5/19/2011

Simple HTML5 Drawing App + Saving The Files With Ajax

This is a simple drawing board app that allows user draw on a canvas, pick several brush sizes and colors and save his image (I'll leave part of the last to you).

You can see how this app works live on the Draw a Robot site. It uses HTML5 canvas and works in all modern browsers except Internet Explorer.

Some important parts of the javascript code are taken from this tutorial. William's app is more impressive. Mine is simpler and aims to explain it in understandable way (William's tutorial is a bit complex). Let's start:

Creating the canvas

<canvas id="drawingCanvas" width="550" height="450" style="border:1pt solid black;margin:auto;cursor:crosshair;clear:both;">
</canvas>


If you don't care about Internet explorer, that's it. We just add some styling to it and make the cursor crossed.

Create the brush sizes and color selectors


<div style="float:left;">Colors:</div> <a href="#" class="colorPicker" onclick="setColor('#FFF');return false;" style="background:#FFF;">&nbsp;</a>
<a class="colorPicker" href="#" onclick="setColor('#000');return false;" style="background:#000;">&nbsp;</a>
<a class="colorPicker" href="#" onclick="setColor('#FF0000');return false;" style="background:#FF0000;">&nbsp;</a>
<a class="colorPicker" href="#" onclick="setColor('#00FF00');return false;" style="background:#00FF00;">&nbsp;</a>
<a class="colorPicker" href="#" onclick="setColor('#0000FF');return false;" style="background:#0000FF;">&nbsp;</a>
<a class="colorPicker" href="#" onclick="setColor('#FFFF00');return false;" style="background:#FFFF00;">&nbsp;</a>
<a class="colorPicker" href="#" onclick="setColor('#00FFFF');return false;" style="background:#00FFFF;">&nbsp;</a>

<div style="clear:both;">&nbsp;</div>

<div style="float:left;">Sizes:</div>
<a href="#" class="colorPicker" onclick="setSize(2);return false;" style="width:2px;height:2px;margin-left:15px;">&nbsp;</a>
<a href="#" class="colorPicker" onclick="setSize(5);return false;" style="width:5px;height:5px;margin-left:15px;">&nbsp;</a>
<a href="#" class="colorPicker" onclick="setSize(10);return false;" style="width:10px;height:10px;margin-left:15px;">&nbsp;</a>
<a href="#" class="colorPicker" onclick="setSize(25);return false;" style="width:25px;height:25px;margin-left:15px;">&nbsp;</a>

<div style="clear:both;">&nbsp;</div>

<p style="clear:both;"><input type="button" value="Clear Canvas" onclick="clearCanvas();">
<input type="button" value="Save My Drawing" onclick="centerElt('saveDrawing',400,300);"></p>


This code adds size selection buttons, color selectiors, and button for saving.

Obviously you can use better CSS to save some code.

Note that Save my drawing users a function that is not published here to keep things simpler. It centers a popup on the screen. You can find or code such function yourself, or simply display the saving form under the canvas without fancy effects. (Let me know in the comments if you need clarification.

The save form

The save form is not important for this tutorial either. You can see the one at the Draw a Robot site, but the form can contain any fields you wish. Maybe image name, description, author name and so on.

The Javascript

After opening a javascript tag, you'll need the following code. I'll input all the explanations to it as javascript comments so you can directly copy the code and use it.

Please note: the javascript below depends on jQuery! If you don't store local copy of jQuery, you need to insert this code in the header of your page:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>

Now your javascript follows:

<script type="text/javascript">
/* some code used from http://www.williammalone.com/articles/create-html5-canvas-javascript-drawing-app/ */

/* Some global initializations follow. The first 2 arays will store all mouse positions 
on X and Y, the 3rd one stores the dragged positions. 
The variable paint is a boolean, and then follow the default values 
which we use to start */
var clickX = new Array();
var clickY = new Array();
var clickDrag = new Array();
var paint;
var defaultColor="#000";
var defaultShape="round";
var defaultWidth=5;

// creating the canvas element
var canvas = document.getElementById('drawingCanvas');

if(canvas.getContext) 
{
    // Initaliase a 2-dimensional drawing context
    var context = canvas.getContext('2d');
    
    // set the defaults
    context.strokeStyle = defaultColor;
    context.lineJoin = defaultShape;
    context.lineWidth = defaultWidth;
}

// binding events to the canvas
$('#drawingCanvas').mousedown(function(e){
  var mouseX = e.pageX - this.offsetLeft;
  var mouseY = e.pageY - this.offsetTop;
  
  paint = true; // start painting
  addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);

  // always call redraw
  redraw();
});

$('#drawingCanvas').mousemove(function(e){
  if(paint){
    addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
    redraw();
  }
});

// when mouse is released, stop painting, clear the arrays with dots
$('#drawingCanvas').mouseup(function(e){
  paint = false;
  
  clickX = new Array();
  clickY = new Array();
  clickDrag = new Array();
});

// stop painting when dragged out of the canvas
$('#drawARobot').mouseleave(function(e){
  paint = false;
});

// The function pushes to the three dot arrays
function addClick(x, y, dragging)
{
  clickX.push(x);
  clickY.push(y);
  clickDrag.push(dragging);
}

// this is where actual drawing happens
// we add dots to the canvas
function redraw(){
    
  for(var i=0; i < clickX.length; i++)
  {  
    context.beginPath();
    if(clickDrag[i] && i){
      context.moveTo(clickX[i-1], clickY[i-1]);
     }else{
       context.moveTo(clickX[i]-1, clickY[i]);
     }
     context.lineTo(clickX[i], clickY[i]);
     context.closePath();
     context.stroke();
  }
}

// this is called when "clear canvas" button is pressed
function clearCanvas()
{
    // both these lines are required to clear the canvas properly in all browsers
    context.clearRect(0,0,canvas.width,canvas.height);
    canvas.width = canvas.width;
    
    // we need to flush the arrays too
    clickX = new Array();
    clickY = new Array();
    clickDrag = new Array();
}

/* Two simple functions, they just assign the selected color and size 
to the canvas object properties */ 
function setColor(col)
{
    context.strokeStyle = col;
}

function setSize(px)
{
    context.lineWidth=px;
}

/* Finally this will send your image to the server-side script which will 
save it to the database or where ever you want it saved.
Note that this function should be called when the button in your save 
form is pressed. The variable frm is the form object. 
Basically the HTML will look like this:
<input type="button" value="Save Drawing" onclick="saveDrawing(this.form);">
 */
function saveDrawing(frm)
{       
    // converting the canvas to data URI
    var strImageData = canvas.toDataURL();  
        
    $.ajax({
        url: "", /* You need to enter the URL of your server side script*/
        type: "post",
          /* add the other variables here or serialize the entire form. 
          Image data must be URI encoded */
        data: "save=1&pic="+encodeURIComponent(strImageData), 
        success: function(msg)
        {
           // display some message and/or redirect
        }
    });
}

Your server side script

It really depends on you. In the Draw a Robot site we just save the robots to the database and then display them in a gallery. You can save the image data in a blob field in the DB. Just have in mind that data / URI images are displayed with the following HTML code:

<img src="encoded image data">

43 comments:

  1. Replies
    1. Hey I just wanted to say that I really enjoyed reading your blog. You have good views, keep up the good informative info. Good Quality and very informative Blog! Contact Vinay Hari Education Consultant

      Delete
  2. cool
    but trying to understand the script
    because i am having some errors in my facebook apps

    make a facebook application

    ReplyDelete
  3. Great work came at a perfect time for me, html5 music playerwould be really cool if we could at least get an option to enable the HTML5 mode player in the next Subsonic release. Not only would it bypass the need for flash, but it also has some extra features (wav playback, etc).It seems the biggest issue would be with flv video, but by transcoding to mp4 instead of flv, that could be solved. Even without the video fix, making it optional would allow those of us the mainly use Subsonic for music to benefit from the new player.

    ReplyDelete
  4. Nice post. Parents are parents, not Gods. Of course they cannot have all the answers. The way you explain things to your kids should do all the work…it all comes under parenthood and your people skills.

    ReplyDelete
  5. hi, how do i save to database? using phpmysql, what params do i set my form?

    thanks for great script

    ReplyDelete
  6. This is actually quite wrong - why do you remember every single point you need to draw and redraw ALL of them after every single movement? All you need to remember is last point and if button was down at that point, then move/draw from last to current point. You don't need to remember all points and you definetly don't need redraw them over and over again.

    ReplyDelete
  7. Good overview, Lee. Using a tool such as can be helpful in assessment and identifying areas of need.

    Website Development company

    ReplyDelete
  8. You will discover some fascinating points in time in this post but I don’t know if I see all of them interior to heart. I am learning great extra challenging on distinct blogs everyday. Lots of people will be benefited from your writing. Cheers!

    Press Release Writers
    Press Release Writing Service

    ReplyDelete
  9. Just like what your website title is. This is really cool. Write something on web development Philippines next time. Thank you.

    ReplyDelete
  10. paint for mac MyBrushes paint for Mac app is the best Mac paint software to paint on Mac infinite canvas and PLAYBACK drawing Paintbrush for Mac.It's good as ms Paint for Mac
    Drawing App MyBrushes is the Best drawing app for ipad to paint on infinite canvas and PLAYBACK each drawing stroke on iPad, iPhone. Download best drawing app for iPad Now.
    avi to mp4 converter Total Video Converter, a very powerful Avi to Mp4 Video Converter, convert any video files to avi, 3gp, mp4, psp, iPod, iPhone, flv, DVD, VCD...

    ReplyDelete
  11. Drawing App : Best drawing app for ipad to paint on infinite drawing canvas and PLAYBACK every drawing stroke on iPad and iPhone. Visit MyBrushes-App.com for best drawing app.

    ReplyDelete
  12. Nice blog Very useful information is providing by ur blog. Great beginning html tutorials Very clear and helpful for beginners.

    ReplyDelete
  13. These all are notable facts… I stick with responsive website design for my business. With the mobile marketing is at its peak stage, having website that goes comfy on all devices will help your business. You can check my website for more details on the importance of responsive website design. PHP Training in Chennai | Best PHP training in Chennai | PHP Training Institute in Chennai

    ReplyDelete
  14. Thanks for your informative article. Your blog is loaded with awesome information. Please include RSS field shat that we can receive your latest post direct to my inbox. Wordpress Course in Chennai

    ReplyDelete
  15. Thanks for a great information in your blog.I have read all the post of your blog.Great work on PHP

    ReplyDelete
  16. Thanks for the great information in your blog PHP

    ReplyDelete
  17. Best SQL Query Tuning Training Center In Chennai This information is impressive; I am inspired with your post writing style & how continuously you describe this topic. After reading your post, thanks for taking the time to discuss this, I feel happy about it and I love learning more about this topic..

    ReplyDelete
  18. Great..You have clearly explained about Simple HTML5 Drawing App + Saving The Files With Ajax..Its very easy to understand..Keep on sharing..
    PHP training in chennai

    ReplyDelete
  19. Thanks for sharing this informative information...You may also refer....
    How to migrate from a typical HTML4 page to a typical HTML5 page.
    www.s4techno.com/blog/2016/08/30/html5-migration/

    ReplyDelete
  20. My friend Suggest me this blog and I can say this is the best blog to get the basic knowledge.Thank you so much for this Selenium Training in Chennai

    ReplyDelete


  21. Thank you for the info. It sounds pretty user friendly. I guess I’ll pick one up for fun. thank u

    iPad Service Center in Chennai - Service Locations

    ReplyDelete
  22. Thanks for sharing this informative information...You may also refer....
    oracle training in chennai

    ReplyDelete
  23. Well explained. Got to learn new things from your Blog on Appium.Appium training in chennai

    ReplyDelete
  24. Wonderful blog.. Thanks for sharing informative blog.. its very useful to me..

    iOS Training in Chennai

    ReplyDelete
  25. Thank You for sharing your article. I like it. We provide TIBCO Online Training in Hyderabad.

    ReplyDelete

  26. Hai Author Good Information that i found here,do not stop sharing and Please keep updating us..... Thanks

    ReplyDelete
  27. This is excellent information. It is amazing and wonderful to visit your site.Thanks for sharing this information,this is useful to me...
    Android Training in Chennai
    Ios Training in Chennai

    ReplyDelete
  28. I am expecting more interesting topics from you. And this was nice content and definitely it will be useful for many people.

    Android App Development Company

    ReplyDelete
  29. Thanks for your information and valuable time . Great article. much more helpful to all.
    Android Training in chennai

    ReplyDelete
  30. I am expecting more interesting topics from you. And this was nice content and definitely it will be useful for many people.
    iOS App Development Company
    iOS App Development Company

    ReplyDelete
  31. These ways are very simple and very much useful, as a beginner level these helped me a lot thanks fore sharing these kinds of useful and knowledgeable information.
    Fitness SMS
    Fitness Text
    Salon SMS
    Salon Text
    Investor Relation SMS
    Investor Relation Text

    ReplyDelete
  32. great and nice blog thanks sharing..I just want to say that all the information you have given here is awesome...Thank you very much for this one.
    web design Company
    web development Company
    web design Company in chennai
    web development Company in chennai
    web design Company in India
    web development Company in India

    ReplyDelete
  33. it is really amazing...thanks for sharing....provide more useful information...
    Mobile app development company

    ReplyDelete