![]() |
![]() |
Accueil > Intranet Michel Buffa > HTML5 tutorial for WWW 2014 - Seoul > HTML5 tutorial for WWW 2013: study a paint program
HTML5 tutorial for WWW 2013: study a paint programDe $1Table des matières
IntroductionIn this tutorial, we will take a step by step look at a Paint program written in pure HTML5/JavaScript/CSS, based on the <canvas> element, We will start with a very simple application and build on it, refactor it to make the code easier to understand, and finish with a real paint program. This wrap up is an extract from a tutorial that has been given at the international conference WWW 2012, in which we added multi-participant features using WebSockets.All the source files you will need are included in this zip archive (4Mbytes). Unzip, go in the "Paint_HTML5_Multi_Tutorial". You will find subdirectories step1, step2, etc. corresponding to each step described in this document. We assume you unzipped the archive from the previous step. Go to the directory where you unzipped the files. You should see a directory named "step 1", open the paint.html file from this directory in your browser. You should see something like this, where every mouse move draws a non interruptible path: Now, look at the different files. Start with the paint.html file, noticing the first lines:
The DOCTYPE is the brand new ultra-simple HTML5 DOCTYPE! Notice that if you write ANYTHING before this DOCTYPE line, IE9 will not consider the file as HTML5, and you will no be able to run the example! The <canvas> tag in the page will be ignored. Other browsers will however do nothing nasty if you write some comment at the top of the document. Then, we declare a CSS and some JavaScript scripts. We will use jQuery for most DOM manipulation and event handling. HTML5 proposes the new document.querySelector(...) that behaves closely like jQuery selectors. The file paint.js holds most of the code for a small "draw when mouse moves" paint program, while utils.js contains a utility function for getting a correct mouse cursor position, dealing with most of the annoying cases. When the document is fully loaded and the DOM ready, we create a Paint object, that will hold most of our JavaScript code. The parameter "canvasMain" passed when we constructed the Paint object is the Id of the <canvas> tag you will find in the HTML part of the page : Let's have a look at the PaintObject code in the paint.js file. First we get 1) a reference to the canvas element and 2) a context object in order to draw in the canvas:
We also bind a mouse move listener to the canvas:
The mouse listener is a method of the PaintObject that draws a line at each mouse move, from the previous mouse position to the current one:
Notice that in order to draw a line we declare a path, we move to a position, we draw a line to another position, we close the path. The path is drawn at the mainContext.stroke() (line 18) call. It will be drawn with the current mainContext.strokeStyle value, which is defaulted to Black. Be careful: just forget to close the path and at every mouse move you will draw the whole path from the beginning! In fact, mainContext.stroke() draws every draw primitive declared since the context.beginPath() call. If a beginPath() is called while a path is not closed, it is ignored. Notice the trick we use in order to set the size of the canvas depending on the size of the browser. Instead of using CSS percentages on canvas width and height, resulting in ugly scaling of canvas content, we adjust the size with a piece of JavaScript code:
Go into the step 2 directory. You may try the example by opening paint.html in your browser. This time we draw only when the mouse moves with a mouse button pressed. We also separated the code that draws from the initialization of the PaintObject. The file drawingtools.js will hold "drawing objects" like pencil, line, rectangle, circle, and so on, while paint.js will just do the job of creating contexts, binding events, etc. We used jQuery to bind different mouse events to the canvas (in paint.js) ...and here is the drawingtool.js content with only a tool that draws like a pencil (notice the 3 listener methods for mouseDown, mouseMove and mouseUp events):
Step 3: add a second, transparent canvas on top of the main canvas, for drawing elastic linesGo into the step 3 directory. You may try the example by opening paint.html in your browser. This example shows an interesting use of canvases: they can be layered one on top of another. Using a CSS relative position and the z-index CSS property with different values, they can act as layers in photoshop. By default they are transparent, and if you use the context.clearRect(x, y, width, height) function you will make a transparent rectangle and be able to "see through" it. We will use this feature to draw an elastic line (lines that follow the mouse position) on a transparent front canvas, without modifying the main canvas behind. In order to animate the line when the mouse moves, we clear the front canvas before drawing a line in its new position. Adding a new canvas on top of the previous one This is done in paint.js: We added a line drawing tool in drawingtools.js We declared an array that will hold the different drawing tools (pencil, line, etc):
And the event binding has been modified in order to call the current drawing tool mouse listener method :
...notice that in the line drawing tool (in drawingtools.js) we draw only in the front canvas, and before any draw we clear the front canvas:
In the paint.html file, we added some spans in order to select the current tool: And in paint.js we detect clicks on them:
Small problem : how can we make the line stay on the drawing when we draw another line ? Step 4: draw the front canvas on the main canvas on mouse release, when drawing linesGo into the step 4 directory. You may try the example by opening paint.html in your browser. This time when we release the mouse button the line is drawn and will stay in the main drawing, even if we draw other elastic lines. Question: how to fix the previous version where lines "did not remain" when we released the mouse button ? Answer: we just draw the front canvas on the the main canvas on mouseUp events ! In paint.js we added a drawFrontCanvasOnMainCanvas() method on the PaintObject:
Notice that we use a drawImage() call from a canvas context object. Indeed, we can draw a canvas on a canvas! And we call this method from the mouseUp() listener method of the line drawing tool:
Step 5: adding a rectangle and a Circle toolGo into the step 5 directory. You may try the example by opening paint.html in your browser. This time, the same way we did the line tool, we added two new tools: one for drawing elastic rectangles and one for drawing elastic circles. You may look at these tools in drawingtools.js. Now that we have a small framework, you can try to add your own tools for drawing ellipses, images etc. (NOTE: this is part of the assignment for this chapter) Go into the step 6 directory. You may try the example by opening paint.html in your browser. This time we added new HTML5 input types in the graphic user interface:
We used a <input type="range".../> for selecting the line width. This will work in Opera, Webkit based browser. It is not yet supported by Firefox, but will work nevertheless if you enter a numeric value. For color selection we used a "polyfill", a <input class="color" /> that works with the jscolor.js library. If you are running a browser that supports the HTML5 <input type="color"/> then change the code to display a nice color chooser natively. In paint.js we handle the values of these fields in order to keep the contexts for both canvases (mainCanvas and frontCanvas) up to date: This way, all the calls to stroke() or fill() using any of the contexts will draw a shape using the selected corresponding color.
Mots clés:
|
||||||||||||||||||||||||||
Powered by MindTouch Deki Open Source Edition v.8.08 |