Skip to content Skip to sidebar Skip to footer

drawing dots in 3d html 5

You are here: Home Dive Into HTML5


Allow'due south Phone call It A
Draw(ing Surface)

Diving In

HTML 5 defines the <canvas> chemical element as "a resolution-dependent bitmap sail which tin can be used for rendering graphs, game graphics, or other visual images on the fly." A canvas is a rectangle in your page where yous can utilise JavaScript to draw annihilation y'all want.

Basic <canvas> back up
IE Firefox Safari Chrome Opera iPhone Android
7.0+* three.0+ 3.0+ 3.0+ 10.0+ 1.0+ 1.0+
* Net Explorer 7 and 8 require the tertiary-party explorercanvas library. Internet Explorer 9 supports <canvas> natively.

So what does a canvas look like? Nothing, really. A <sheet> element has no content and no border of its ain.

 ↜ Invisible canvas

The markup looks like this:

        <canvass width="300" height="225"></canvas>      

Permit's add a dotted border then we can see what we're dealing with.

 ↜ Canvas with border

Y'all tin have more than than one <sail> element on the same page. Each sheet will prove upwardly in the DOM, and each canvas maintains its ain state. If yous give each canvas an id attribute, you can admission them just similar whatever other element.

Let'due south aggrandize that markup to include an id attribute:

        <canvass id="a" width="300" height="225"></canvas>      

Now you tin can easily find that <canvas> element in the DOM.

        var a_canvas = certificate.getElementById("a");      

Simple Shapes

IE Firefox Safari Chrome Opera iPhone Android
seven.0+* 3.0+ three.0+ 3.0+ 10.0+ 1.0+ 1.0+
* Internet Explorer vii and viii require the 3rd-party explorercanvas library. Internet Explorer 9 supports <canvas> shapes natively.

Every sail starts out blank. That's slow! Let'due south draw something.

 ⇜ Click to depict on this sail

The onclick handler called this function:

        function draw_b() {   var b_canvas = document.getElementById("b");   var b_context = b_canvas.getContext("2d");   b_context.fillRect(fifty, 25, 150, 100); }      

The ist line of the function is nothing special; information technology just finds the <canvas> chemical element in the DOM.

So there'due south this

        part draw_b() {   var b_canvas = document.getElementById("b");                      var b_context = b_canvas.getContext("2d");          b_context.fillRect(l, 25, 150, 100); }      

man drawing in front of a mirror

Every canvass has a cartoon context, which is where all the fun stuff happens. One time you've establish a <sheet> element in the DOM (by using document.getElementById() or whatever other method you like), you lot call its getContext() method. You must pass the cord "2d" to the getContext() method.

Q: Is at that place a 3-D canvas?
A: Not yet. Individual vendors take experimented with their own iii-dimensional canvas APIs, but none of them take been standardized. The HTML5 specification notes, "A future version of this specification will probably define a 3d context."

Then, you have a <canvas> element, and you lot have its drawing context. The drawing context is where all the drawing methods and properties are defined. There'southward a whole grouping of backdrop and methods devoted to cartoon rectangles:

  • The fillStyle property can exist a CSS color, a pattern, or a gradient. (More on gradients shortly.) The default fillStyle is solid blackness, but yous can fix it to whatever you similar. Each drawing context remembers its own properties as long every bit the page is open, unless you do something to reset it.
  • fillRect(10, y, width, tiptop) draws a rectangle filled with the current make full way.
  • The strokeStyle belongings is similar fillStyle — it can be a CSS color, a design, or a gradient.
  • strokeRect(ten, y, width, tiptop) draws an rectangle with the current stroke style. strokeRect doesn't make full in the middle; information technology just draws the edges.
  • clearRect(ten, y, width, height) clears the pixels in the specified rectangle.

Ask Professor Markup

Q: Can I "reset" a sheet?
A: Yes. Setting the width or height of a <sail> chemical element will erase its contents and reset all the properties of its drawing context to their default values. You don't even need to alter the width; you lot can simply fix information technology to its current value, like this:

              var b_canvas = document.getElementById("b");                b_canvas.width = b_canvas.width;                          

Getting back to that code sample in the previous example…

Depict a rectangle

        var b_canvas = document.getElementById("b"); var b_context = b_canvas.getContext("2d");          b_context.fillRect(fifty, 25, 150, 100);              

Calling the fillRect() method draws the rectangle and fills it with the current fill manner, which is black until you alter it. The rectangle is bounded by its upper-left corner (50, 25), its width (150), and its height (100). To get a improve picture of how that works, permit'southward wait at the sheet coordinate arrangement.

Canvas Coordinates

The canvas is a ii-dimensional grid. The coordinate (0, 0) is at the upper-left corner of the canvas. Along the X-axis, values increment towards the right edge of the canvas. Forth the Y-axis, values increment towards the bottom edge of the sail.

Sheet coordinates diagram

That coordinate diagram was drawn with a <sail> element. It comprises

  • a prepare of fair vertical lines
  • a set up of off-white horizontal lines
  • two black horizontal lines
  • two small-scale black diagonal lines that class an pointer
  • two blackness vertical lines
  • two small black diagonal lines that form another pointer
  • the letter "x"
  • the letter of the alphabet "y"
  • the text "(0, 0)" nigh the upper-left corner
  • the text "(500, 375)" near the lower-correct corner
  • a dot in the upper-left corner, and another in the lower-right corner

First, nosotros need to ascertain the <sheet> element itself. The <canvas> chemical element defines the width and superlative, and the id and so we can find it later on.

        <canvas id="c" width="500" top="375"></canvas>      

And so we demand a script to find the <sheet> element in the DOM and get its drawing context.

        var c_canvas = document.getElementById("c"); var context = c_canvas.getContext("2d");      

Now we can first drawing lines.

Paths

IE Firefox Safari Chrome Opera iPhone Android
vii.0+* 3.0+ 3.0+ 3.0+ 10.0+ one.0+ i.0+
* Internet Explorer vii and 8 require the third-party explorercanvas library. Internet Explorer 9 supports <canvas> paths natively.

gerbil sitting on a chair with a quill and ink jar

Imagine you're drawing a motion picture in ink. You don't desire to merely dive in and outset drawing with ink, because y'all might make a mistake. Instead, you sketch the lines and curves with a pencil, and once you're happy with information technology, you trace over your sketch in ink.

Each sheet has a path. Defining the path is like drawing with a pencil. You tin can draw whatever y'all like, but it won't be role of the finished product until you pick upwardly the quill and trace over your path in ink.

To describe direct lines in pencil, you use the following two methods:

  1. moveTo(x, y) moves the pencil to the specified starting point.
  2. lineTo(x, y) draws a line to the specified ending signal.

The more you call moveTo() and lineTo(), the bigger the path gets. These are "pencil" methods — you can call them as frequently as y'all like, but you lot won't see annihilation on the sail until you call one of the "ink" methods.

Allow'south begin by cartoon the off-white filigree.

        for (var x = 0.v; ten < 500; 10 += 10) {   context.moveTo(x, 0);          context.lineTo(10, 375);          }      

 ⇜ Draw vertical lines

        for (var y = 0.5; y < 375; y += 10) {   context.moveTo(0, y);          context.lineTo(500, y);          }      

 ⇜ Draw horizontal lines

Those were all "pencil" methods. Nothing has actually been fatigued on the canvas yet. We need an "ink" method to brand it permanent.

        context.strokeStyle = "#eee";          context.stroke();              

stroke() is ane of the "ink" methods. It takes the complex path you divers with all those moveTo() and lineTo() calls, and actually draws it on the canvass. The strokeStyle controls the color of the lines. This is the result:

Enquire Professor Markup

Q: Why did you outset x and y at 0.five? Why not 0?
A: Imagine each pixel as a big square. The whole-number coordinates (0, i, ii…) are the edges of the squares. If you describe a one-unit-wide line betwixt whole-number coordinates, it will overlap opposite sides of the pixel square, and the resulting line will be drawn 2 pixels wide. To draw a line that is simply one pixel broad, you demand to shift the coordinates past 0.5 perpendicular to the line's management.

For case, if you effort to draw a line from (1, 0) to (i, iii), the browser will draw a line roofing 0.5 screen pixels on either side of x=1. The screen can't display half a pixel, and then it expands the line to cover a full of two pixels:

A line from (1,0) to (1,3) is drawn 2 pixels wide

Simply, if you attempt to draw a line from (1.5, 0) to (1.5, three), the browser will draw a line covering 0.five screen pixels on either side of x=one.5, which results in a true 1-pixel-wide line:

A line from (1.5,0) to (1.5,3) is draw 1 pixel wide

Thanks to Jason Johnson for providing these diagrams.

Now permit's draw the horizontal arrow. All the lines and curves on a path are drawn in the aforementioned colour (or slope — yes, we'll get to those soon). We want to draw the arrow in a different color ink — black instead of off-white — and so we need to start a new path.

A new path

                  context.beginPath();          context.moveTo(0, forty); context.lineTo(240, 40); context.moveTo(260, 40); context.lineTo(500, forty); context.moveTo(495, 35); context.lineTo(500, forty); context.lineTo(495, 45);      

The vertical arrow looks much the same. Since the vertical pointer is the same colour as the horizontal arrow, nosotros exercise not demand to start another new path. The two arrows volition be part of the aforementioned path.

        context.moveTo(60, 0); context.lineTo(threescore, 153); context.moveTo(60, 173); context.lineTo(sixty, 375); context.moveTo(65, 370); context.lineTo(60, 375); context.lineTo(55, 370);      

 ↜ Non a new path

I said these arrows were going to be black, simply the strokeStyle is even so off-white. (The fillStyle and strokeStyle don't go reset when you start a new path.) That's OK, because we've just run a series of "pencil" methods. But before we draw information technology for real, in "ink," we need to prepare the strokeStyle to blackness. Otherwise, these two arrows will be fair, and we'll hardly be able to see them! The following lines change the color to black and draw the lines on the canvas:

        context.strokeStyle = "#000"; context.stroke();      

This is the result:

Text

IE Firefox Safari Chrome Opera iPhone Android
7.0+* three.0+ 3.0+ 3.0+ 10.0+ 1.0+ 1.0+
* Internet Explorer seven and viii require the third-party explorercanvas library. Cyberspace Explorer 9 supports sail text natively.
† Mozilla Firefox 3.0 requires a compatibility shim.

In addition to drawing lines on a canvas, yous can also depict text on a canvas. Dissimilar text on the surrounding spider web folio, there is no box model. That means none of the familiar CSS layout techniques are available: no floats, no margins, no padding, no word wrapping. (Maybe you think that's a good matter!) You lot can set a few font attributes, then you option a point on the canvas and draw your text there.

The following font attributes are available on the drawing context:

  • font can be anything you would put in a CSS font dominion. That includes font style, font variant, font weight, font size, line height, and font family.
  • textAlign controls text alignment. It is similar (but non identical) to a CSS text-align rule. Possible values are offset, end, left, correct, and center.
  • textBaseline controls where the text is drawn relative to the starting indicate. Possible values are tiptop, hanging, middle, alphabetic, ideographic, or bottom.

textBaseline is catchy, because text is tricky (English text isn't, just y'all tin draw any Unicode character y'all like on a sheet, and Unicode is tricky). The HTML5 specification explains the different text baselines:

The elevation of the em square is roughly at the acme of the glyphs in a font, the hanging baseline is where some glyphs like are anchored, the eye is half-style between the top of the em square and the bottom of the em square, the alphabetic baseline is where characters like Á, ÿ, f, and Ω are anchored, the ideographic baseline is where glyphs similar and are anchored, and the bottom of the em foursquare is roughly at the bottom of the glyphs in a font. The pinnacle and bottom of the bounding box tin can exist far from these baselines, due to glyphs extending far outside the em square.

diagram of different values of the textBaseline property

For unproblematic alphabets like English, yous can safely stick with height, middle, or bottom for the textBaseline property.

Let's depict some text! Text drawn inside the sheet inherits the font size and way of the <sheet> element itself, merely yous can override this past setting the font holding on the drawing context.

                  context.font = "bold 12px sans-serif";          context.fillText("x", 248, 43); context.fillText("y", 58, 165);      

 ↜ Change the font style

The fillText() method draws the actual text.

        context.font = "assuming 12px sans-serif";          context.fillText("x", 248, 43);          context.fillText("y", 58, 165);      

 ⇜ Draw the text

Ask Professor Markup

Q: Tin I use relative font sizes to draw text on a canvas?
A: Yes. Like every other HTML element on your page, the <canvass> chemical element itself has a computed font size based on your page'due south CSS rules. If yous set the context.font holding to a relative font size like 1.5em or 150%, your browser multiplies this past the computed font size of the <canvass> element itself.

For the text in the upper-left corner, let's say I want the superlative of the text to be at y=five. Only I'm lazy — I don't want to mensurate the height of the text and calculate the baseline. Instead, I tin can prepare textBaseline to tiptop and pass in the upper-left coordinate of the text's bounding box.

        context.textBaseline = "elevation"; context.fillText("( 0 , 0 )",          8, v);      

Now for the text in the lower-right corner. Let's say I want the bottom-correct corner of the text to exist at coordinates (492,370) — simply a few pixels away from the lesser-right corner of the sail — but I don't want to measure out the width or summit of the text. I can ready textAlign to correct and textBaseline to bottom, then telephone call fillText() with the bottom-right coordinates of the text'southward bounding box.

        context.textAlign = "right"; context.textBaseline = "bottom"; context.fillText("( 500 , 375 )",          492, 370);      

And this is the result:

Oops! We forgot the dots in the corners. We'll see how to draw circles a little later. For now, I'll cheat a little and draw them as rectangles.

        context.fillRect(0, 0, three, 3); context.fillRect(497, 372, 3, 3);      

 ⇜ Draw 2 "dots"

And that's all she wrote! Hither is the concluding production:

Gradients

IE Firefox Safari Chrome Opera iPhone Android
linear gradients 7.0+* 3.0+ iii.0+ 3.0+ 10.0+ ane.0+ 1.0+
radial gradients ix.0+ 3.0+ iii.0+ 3.0+ 10.0+ 1.0+ 1.0+
* Internet Explorer 7 and 8 crave the third-party explorercanvas library. Internet Explorer nine supports <sail> gradients natively.

Earlier in this affiliate, you learned how to draw a rectangle filled with a solid color, then a line stroked with a solid color. But shapes and lines aren't limited to solid colors. You tin can do all kinds of magic with gradients. Allow'south await at an example.

The markup looks the aforementioned as any other canvas.

        <canvas id="d" width="300" height="225"></canvas>      

First, we need to find the <sail> element and its drawing context.

        var d_canvas = document.getElementById("d"); var context = d_canvas.getContext("second");      

In one case we have the drawing context, we can first to define a gradient. A gradient is a smooth transition betwixt two or more colors. The canvas cartoon context supports ii types of gradients:

  1. createLinearGradient(x0, y0, x1, y1) paints along a line from (x0, y0) to (x1, y1).
  2. createRadialGradient(x0, y0, r0, x1, y1, r1) paints along a cone between 2 circles. The first three parameters correspond the first circle, with origin (x0, y0) and radius r0. The last 3 parameters correspond the end circle, with origin (x1, y1) and radius r1.

Permit'southward make a linear slope. Gradients can be any size, only I'll make this gradient be 300 pixels wide, like the canvas.

Create a gradient object

        var my_gradient =          context.createLinearGradient(0, 0, 300, 0);              

Because the y values (the 2nd and fourth parameters) are both 0, this gradient volition shade evenly from left to right.

Once we accept a slope object, we can define the gradient's colors. A gradient has 2 or more than colour stops. Color stops can exist anywhere along the slope. To add a color stop, yous need to specify its position forth the gradient. Gradient positions tin be anywhere between 0 to 1.

Let'due south define a gradient that shades from black to white.

        my_gradient.addColorStop(0, "black"); my_gradient.addColorStop(1, "white");      

Defining a gradient doesn't draw anything on the canvas. It's merely an object tucked away in retentiveness somewhere. To draw a gradient, you lot set up your fillStyle to the gradient and depict a shape, like a rectangle or a line.

Make full style is a gradient

                  context.fillStyle = my_gradient;          context.fillRect(0, 0, 300, 225);      

And this is the result:

Suppose you want a slope that shades from superlative to lesser. When you create the gradient object, go on the x values (ist and 3rd parameters) constant, and make the y values (2nd and 4thursday parameters) range from 0 to the summit of the canvass.

ten values are 0, y values vary

        var my_gradient = context.createLinearGradient(0, 0, 0, 225); my_gradient.addColorStop(0, "black"); my_gradient.addColorStop(one, "white"); context.fillStyle = my_gradient; context.fillRect(0, 0, 300, 225);      

And this is the event:

Yous tin also create gradients along a diagonal.

both x and y values vary

        var my_gradient = context.createLinearGradient(0, 0, 300, 225); my_gradient.addColorStop(0, "black"); my_gradient.addColorStop(1, "white"); context.fillStyle = my_gradient; context.fillRect(0, 0, 300, 225);      

And this is the result:

Images

IE Firefox Safari Chrome Opera iPhone Android
7.0+* 3.0+ 3.0+ 3.0+ 10.0+ 1.0+ 1.0+
* Internet Explorer vii and viii require the third-party explorercanvas library. Cyberspace Explorer nine supports <canvas> images natively.

Hither is a cat:

sleeping cat

 ⇜ An <img> chemical element

Here is the same true cat, drawn on a sail:

The canvas drawing context defines a drawImage() method for drawing an epitome on a canvass. The method can take three, v, or nine arguments.

  • drawImage(image, dx, dy) takes an epitome and draws information technology on the canvas. The given coordinates (dx, dy) will exist the upper-left corner of the image. Coordinates (0, 0) would describe the image at the upper-left corner of the canvass.
  • drawImage(image, dx, dy, dw, dh) takes an prototype, scales it to a width of dw and a height of dh, and draws it on the canvas at coordinates (dx, dy).
  • drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) takes an image, clips it to the rectangle (sx, sy, sw, sh), scales it to dimensions (dw, dh), and draws it on the canvas at coordinates (dx, dy).

The HTML5 specification explains the drawImage() parameters:

The source rectangle is the rectangle [within the source image] whose corners are the four points (sx, sy), (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh).

The destination rectangle is the rectangle [within the canvass] whose corners are the iv points (dx, dy), (dx+dw, dy), (dx+dw, dy+dh), (dx, dy+dh).

diagram of drawImage parameters

To draw an epitome on a canvas, you need an epitome. The epitome tin be an existing <img> element, or you tin can create an Image() object with JavaScript. Either style, yous need to ensure that the paradigm is fully loaded before you tin can describe information technology on the canvas.

If you're using an existing <img> element, y'all tin can safely draw it on the sail during the window.onload event.

using an <img> element

        <img          id="true cat"          src="images/cat.png" alt="sleeping cat" width="177" height="113"> <canvas id="east" width="177" height="113"></canvas> <script>          window.onload          = part() {   var canvass = document.getElementById("east");   var context = canvas.getContext("2d");   var cat = document.getElementById("cat");          context.drawImage(cat, 0, 0);          }; </script>      

If you're creating the image object entirely in JavaScript, y'all tin safely draw the epitome on the sail during the Image.onload issue.

using an Image() object

        <canvass id="e" width="177" height="113"></canvas> <script>   var sail = document.getElementById("eastward");   var context = canvas.getContext("2d");   var cat =          new Image();   cat.src = "images/true cat.png";          cat.onload          = function() {     context.drawImage(cat, 0, 0);   }; </script>      

The optional 3rd and 4th parameters to the drawImage() method control paradigm scaling. This is the aforementioned image, scaled to one-half its width and elevation and drawn repeatedly at different coordinates within a single canvas.

Hither is the script that produces the "multicat" event:

        cat.onload = function() {   for (var x = 0, y = 0;        x < 500 && y < 375;        x += 50, y += 37) {     context.drawImage(true cat, 10, y,          88, 56);   } };              

 ⇜ Calibration the epitome

All this effort raises a legitimate question: why would you want to draw an image on a canvass in the first place? What does the extra complexity of epitome-on-a-canvass buy you over an <img> element and some CSS rules? Even the "multicat" consequence could exist replicated with ten overlapping <img> elements.

The uncomplicated answer is, for the aforementioned reason you might want to describe text on a canvas. The canvas coordinates diagram included text, lines, and shapes; the text-on-a-canvas was only 1 part of a larger work. A more complex diagram could easily use drawImage() to include icons, sprites, or other graphics.

What About IE?

Versions of Internet Explorer before 9.0 do non support the canvas API. (IE9 does fully support the canvas API.) However, those older versions of Internet Explorer practice back up a Microsoft-proprietary engineering science called VML, which can practise many of the same things as the <sheet> chemical element. And thus, excanvas.js was born.

Explorercanvas (excanvas.js) is an open up source, Apache-licensed JavaScript library that implements the canvas API in Internet Explorer. To use it, include the following <script> element at the top of your page.

        <!DOCTYPE html> <html> <head>   <meta charset="utf-eight">   <championship>Dive Into HTML5</title>          <!--[if lt IE 9]>     <script src="excanvas.js"></script> <![endif]-->          </head> <body>   ... </torso> </html>              

The <!--[if lt IE 9]> and <![endif]--> bits are conditional comments. Internet Explorer interprets them like an if statement: "if the current browser is a version of Internet Explorer prior to (but not including) version 9, and so execute this block." Every other browser will treat the unabridged block as an HTML annotate. The internet result is that Internet Explorer 7 and 8 will download the excanvas.js script and execute it, but other browsers volition ignore the script altogether (not download it, non execute it, not anything). This makes your page load faster in browsers that implement the sail API natively.

One time you include the excanvas.js in the <head> of your page, yous don't need to do annihilation else to accomodate Internet Explorer. Just include <canvas> elements in your markup, or create them dynamically with JavaScript. Follow the instructions in this affiliate to become the drawing context of a <canvas> chemical element, and you lot tin can draw shapes, text, and patterns.

Well… not quite. There are a few limitations:

  1. Gradients tin can but exist linear. Radial gradients are non supported.
  2. Patterns must be repeating in both directions.
  3. Clipping regions are not supported.
  4. Non-compatible scaling does not correctly scale strokes.
  5. It's tedious. This should not come as a raging daze to anyone, since Internet Explorer's JavaScript parser is slower than other browsers to begin with. In one case you starting time drawing complex shapes via a JavaScript library that translates commands to a completely different applied science, things are going to become bogged down. You won't notice the performance degradation in uncomplicated examples like drawing a few lines and transforming an paradigm, but you'll see it right abroad in one case you beginning doing canvass-based blitheness and other crazy stuff.

There is one more caveat about using excanvas.js, and it'southward a problem that I ran into while creating the examples in this chapter. ExplorerCanvas initializes its ain simulated-canvas interface automatically whenever you include the excanvas.js script in your HTML page. But that doesn't mean that Net Explorer is ready to use it immediately. In certain situations, yous tin can run into a race condition where the faux-canvass interface is about, only not quite, ready to use. The primary symptom of this land is that Internet Explorer will complain that "object doesn't support this property or method" whenever you effort to practise anything with a <canvas> element, such equally get its drawing context.

The easiest solution to this is to defer all of your canvass-related manipulation until afterward the onload event fires. This may be a while — if your folio has a lot of images or videos, they volition delay the onload event — simply it volition give ExplorerCanvas fourth dimension to work its magic.

A Consummate, Live Example

Halma is a centuries-old board game. Many variations exist. In this example, I've created a solitaire version of Halma with 9 pieces on a nine × 9 board. In the beginning of the game, the pieces course a 3 × 3 square in the bottom-left corner of the board. The object of the game is to motion all the pieces so they form a 3 × three square in the upper-right corner of the board, in the least number of moves.

There are two types of legal moves in Halma:

  • Take a slice and move it to whatsoever adjacent empty square. An "empty" foursquare is 1 that does non currently have a piece in it. An "next" square is immediately northward, south, e, west, northwest, northeast, southwest, or southeast of the piece'due south current position. (The board does not wrap around from one side to the other. If a piece is in the left-most column, it can not move west, northwest, or southwest. If a slice is in the bottom-well-nigh row, it tin non movement south, southeast, or southwest.)
  • Take a piece and hop over an next piece, and possibly repeat. That is, if you hop over an adjacent slice, and so hop over another piece next to your new position, that counts as a unmarried motility. In fact, whatever number of hops still counts as a single move. (Since the goal is to minimize the total number of moves, doing well in Halma involves constructing, then using, long bondage of staggered pieces and then that other pieces can hop over them in long sequences.)

Here is the game itself. You tin also play it on a separate folio if you want to poke at it with your browser'due south developer tools.

Moves: 0

How does it work? I'm and so glad you asked. I won't testify all the code hither. (You can meet it at diveintohtml5.org/examples/halma.js.) I'll skip over most of the gameplay code itself, just I want to highlight a few parts of the code that bargain with actually drawing on the canvas and responding to mouse clicks on the canvas chemical element.

During folio load, nosotros initialize the game by setting the dimensions of the <canvass> itself and storing a reference to its drawing context.

        gCanvasElement.width = kPixelWidth; gCanvasElement.peak = kPixelHeight; gDrawingContext = gCanvasElement.getContext("2d");      

Then we do something you haven't seen yet: we add an event listener to the <canvas> element to heed for click events.

        gCanvasElement.addEventListener("click", halmaOnClick, simulated);      

The halmaOnClick() function gets called when the user clicks anywhere within the canvass. Its argument is a MouseEvent object that contains information about where the user clicked.

        office halmaOnClick(east) {     var cell =          getCursorPosition(e);      // the residual of this is just gameplay logic     for (var i = 0; i < gNumPieces; i++) { 	if ((gPieces[i].row == cell.row) &&  	    (gPieces[i].cavalcade == jail cell.column)) { 	    clickOnPiece(i); 	    return; 	}     }     clickOnEmptyCell(prison cell); }      

The next footstep is to take the MouseEvent object and summate which square on the Halma board merely got clicked. The Halma lath takes up the entire canvas, and then every click is somewhere on the board. Nosotros only need to figure out where. This is tricky, considering mouse events are implemented differently in simply nigh every browser.

        function getCursorPosition(e) {     var x;     var y;     if (e.pageX != undefined && due east.pageY != undefined) { 	x = e.pageX; 	y = east.pageY;     }     else { 	x = eastward.clientX + certificate.body.scrollLeft +             document.documentElement.scrollLeft; 	y = e.clientY + document.body.scrollTop +             document.documentElement.scrollTop;     }      

At this point, we take ten and y coordinates that are relative to the certificate (that is, the unabridged HTML page). That'south not quite useful yet. Nosotros want coordinates relative to the canvass.

                  x -= gCanvasElement.offsetLeft;     y -= gCanvasElement.offsetTop;      

Now we have x and y coordinates that are relative to the canvass. That is, if x is 0 and y is 0 at this point, nosotros know that the user only clicked the acme-left pixel of the canvas.

From hither, we can summate which Halma square the user clicked, and so act appropriately.

                  var jail cell = new Cell(Math.flooring(y/kPieceHeight),                         Math.floor(x/kPieceWidth));     return prison cell; }      

Whew! Mouse events are tough. But you can utilise the same logic (in fact, this verbal code) in all of your own sail-based applications. Remember: mouse click → certificate-relative coordinates → canvass-relative coordinates → awarding-specific code.

OK, let's await at the principal drawing routine. Considering the graphics are so simple, I've chosen to clear and redraw the board in its entirety every fourth dimension anything changes within the game. This is not strictly necessary. The canvas drawing context will retain whatever you have previously drawn on it, fifty-fifty if the user scrolls the canvas out of view or changes to another tab and and so comes dorsum later. If yous're developing a canvas-based application with more complicated graphics (such as an arcade game), you can optimize operation by tracking which regions of the canvass are "muddied" and redrawing just the dirty regions. Simply that is outside the scope of this book.

        gDrawingContext.clearRect(0, 0, kPixelWidth, kPixelHeight);      

The board-drawing routine should look familiar. It's similar to how we drew the canvas coordinates diagram earlier in this chapter.

        gDrawingContext.beginPath();  /* vertical lines */ for (var x = 0; x <= kPixelWidth; x += kPieceWidth) {     gDrawingContext.moveTo(0.5 + x, 0);     gDrawingContext.lineTo(0.5 + x, kPixelHeight); }  /* horizontal lines */ for (var y = 0; y <= kPixelHeight; y += kPieceHeight) {     gDrawingContext.moveTo(0, 0.5 + y);     gDrawingContext.lineTo(kPixelWidth, 0.5 +  y); }  /* depict it! */ gDrawingContext.strokeStyle          = "#ccc"; gDrawingContext.stroke();      

The real fun begins when we become to draw each of the individual pieces. A piece is a circle, something we oasis't drawn before. Furthermore, if the user selects a piece in anticipation of moving it, we want to draw that slice as a filled-in circle. Here, the statement p represents a piece, which has row and column properties that denote the piece's current location on the board. We use some in-game constants to translate (column, row) into canvas-relative (ten, y) coordinates, and then draw a circle, then (if the piece is selected) fill in the circle with a solid color.

        office drawPiece(p, selected) {     var column = p.column;     var row = p.row;     var          x          = (column * kPieceWidth) + (kPieceWidth/two);     var          y          = (row * kPieceHeight) + (kPieceHeight/2);     var radius = (kPieceWidth/two) - (kPieceWidth/10);      

That's the end of the game-specific logic. Now we have (x, y) coordinates, relative to the sail, for the eye of the circle we desire to draw. At that place is no circle() method in the canvass API, but there is an arc() method. And really, what is a circumvolve merely an arc that goes all the mode around? Exercise you recall your basic geometry? The arc() method takes a heart point (10, y), a radius, a start and cease angle (in radians), and a direction flag (false for clockwise, truthful for counter-clockwise). You can utilize the Math module that's congenital into JavaScript to calculate radians.

        gDrawingContext.beginPath(); gDrawingContext.arc(x, y, radius, 0,          Math.PI * two, false); gDrawingContext.closePath();      

But wait! Nix has been drawn notwithstanding. Like moveTo() and lineTo, the arc() method is a "pencil" method. To actually draw the circle, we need to set up the strokeStyle and call stroke() to trace it in "ink."

        gDrawingContext.strokeStyle          = "#000"; gDrawingContext.stroke();      

What if the piece is selected? We can re-use the same path we created to depict the outline of the piece, to fill up in the circumvolve with a solid color.

        if (selected) {     gDrawingContext.fillStyle          = "#000";     gDrawingContext.fill(); }      

And that'south… well, that'southward pretty much it. The balance of the plan is game-specific logic — distinguishing between valid and invalid moves, keeping runway of the number of moves, detecting whether the game is over. With nine circles, a few straight lines, and 1 onclick handler, nosotros've created an unabridged game in <canvas>. Huzzah!

Farther Reading

  • Canvas tutorial on Mozilla Developer Center
  • HTML5 canvas — the basics, by Mihai Sucan
  • CanvasDemos.com: demos, tools, and tutorials for the HTML canvas element
  • The canvass chemical element in the HTML5 draft standard
  • Internet Explorer 9 Guide for Developers: HTML5 sheet element

This has been "Let'southward Call It A Describe(ing Surface)." The full table of contents has more if you'd similar to keep reading.

Did Yous Know?

In association with Google Press, O'Reilly is distributing this book in a variety of formats, including paper, ePub, Mobi, and DRM-free PDF. The paid edition is called "HTML5: Upward & Running," and information technology is available now. This chapter is included in the paid edition.

If you liked this chapter and want to show your appreciation, y'all can buy "HTML5: Up & Running" with this affiliate link or purchase an electronic edition directly from O'Reilly. Y'all'll get a book, and I'll get a buck. I practise not currently have direct donations.

Copyright MMIX–MMXI Marker Pilgrim

simmonsoppithatione.blogspot.com

Source: https://diveinto.html5doctor.com/canvas.html

Post a Comment for "drawing dots in 3d html 5"