HTML5 Game Development by Example:Beginner's Guide(Second Edition)
上QQ阅读APP看书,第一时间看更新

Time for action – drawing color circles in the Canvas

  1. First, let's set up the new environment for the example. That is, an HTML file that will contain the canvas element, a jQuery library to help us in JavaScript, a JavaScript file containing the actual drawing logic, and a style sheet:
    index.html
    js/
      js/jquery-2.1.3.js
      js/untangle.js
      js/untangle.drawing.js
      js/untangle.data.js
      js/untangle.input.js
    css/
      css/untangle.css
    images/
  2. Put the following HTML code into the index.html file. It is a basic HTML document containing the canvas element:
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <title>Drawing Circles in Canvas</title>
      <link rel="stylesheet" href="css/untangle.css">
    </head>
    <body>
      <header>
        <h1>Drawing in Canvas</h1>
      </header>  
      
      <canvas id="game" width="768" height="400">
        This is an interactive game with circles and lines connecting them.
      </canvas>
      
    <script src="js/jquery-2.1.3.min.js"></script>
    <script src="js/untangle.data.js"></script>
    <script src="js/untangle.drawing.js"></script>
    <script src="js/untangle.input.js"></script>
    <script src="js/untangle.js"></script>
    </body>
    </html>
  3. Use CSS to set the background color of the Canvas inside untangle.css:
    canvas {
      background: grey;
    }
  4. In the untangle.js JavaScript file, we put a jQuery document ready function and draw a color circle inside it:
    $(document).ready(function(){
      var canvas = document.getElementById("game");  
      var ctx = canvas.getContext("2d");
      ctx.fillStyle = "GOLD";
      ctx.beginPath();
      ctx.arc(100, 100, 50, 0, Math.PI*2, true); 
      ctx.closePath();
      ctx.fill();
    });
  5. Open the index.html file in a web browser and we will get the following screenshot:

What just happened?

We have just created a simple Canvas context with circles on it. There are not many settings for the canvas element itself. We set the width and height of the Canvas, the same as we have fixed the dimensions of real drawing paper. Also, we assign an ID attribute to the Canvas for an easier reference in JavaScript:

<canvas id="game" width="768" height="400">
  This is an interactive game with circles and lines connecting them.
</canvas>

Putting in fallback content when the web browser does not support the Canvas

Not every web browser supports the canvas element. The canvas element provides an easy way to provide fallback content if the canvas element is not supported. The content also provides meaningful information for any screen reader too. Anything inside the open and close tags of the canvas element is the fallback content. This content is hidden if the web browser supports the element. Browsers that don't support canvas will instead display that fallback content. It is good practice to provide useful information in the fallback content. For instance, if the canvas tag's purpose is a dynamic picture, we may consider placing an <img> alternative there. Or we may also provide some links to modern web browsers for the visitor to upgrade their browser easily.

The Canvas context

When we draw in the Canvas, we actually call the drawing API of the canvas rendering context. You can think of the relationship of the Canvas and context as Canvas being the frame and context the real drawing surface. Currently, we have 2d, webgl, and webgl2 as the context options. In our example, we'll use the 2D drawing API by calling getContext("2d").

var canvas = document.getElementById("game");  
var ctx = canvas.getContext("2d");

Drawing circles and shapes with the Canvas arc function

There is no circle function to draw a circle. The Canvas drawing API provides a function to draw different arcs, including the circle. The arc function accepts the following arguments:

Converting degrees to radians

The angle arguments used in the arc function are in radians instead of degrees. If you are familiar with the degrees angle, you may need to convert the degrees into radians before putting the value into the arc function. We can convert the angle unit using the following formula:

radians = π/180 x degrees

Executing the path drawing in the Canvas

When we are calling the arc function or other path drawing functions, we are not drawing the path immediately in the Canvas. Instead, we are adding it into a list of the paths. These paths will not be drawn until we execute the drawing command.

There are two drawing executing commands: one command to fill the paths and the other to draw the stroke.

We fill the paths by calling the fill function and draw the stroke of the paths by calling the stroke function, which we will use later when drawing lines:

ctx.fill();

Beginning a path for each style

The fill and stroke functions fill and draw the paths in the Canvas but do not clear the list of paths. Take the following code snippet as an example. After filling our circle with the color red, we add other circles and fill them with green. What happens to the code is both the circles are filled with green, instead of only the new circle being filled by green:

var canvas = document.getElementById('game');  
var ctx = canvas.getContext('2d');
ctx.fillStyle = "red";
ctx.arc(100, 100, 50, 0, Math.PI*2, true); 
ctx.fill();

ctx.arc(210, 100, 50, 0, Math.PI*2, true);
ctx.fillStyle = "green";
ctx.fill();

This is because, when calling the second fill command, the list of paths in the Canvas contains both circles. Therefore, the fill command fills both circles with green and overrides the red color circle.

In order to fix this issue, we want to ensure we call beginPath before drawing a new shape every time.

The beginPath function empties the list of paths, so the next time we call the fill and stroke commands, they will only apply to all paths after the last beginPath.

Have a go hero

We have just discussed a code snippet where we intended to draw two circles: one in red and the other in green. The code ends up drawing both circles in green. How can we add a beginPath command to the code so that it draws one red circle and one green circle correctly?

Closing a path

The closePath function will draw a straight line from the last point of the latest path to the first point of the path. This is called closing the path. If we are only going to fill the path and are not going to draw the stroke outline, the closePath function does not affect the result. The following screenshot compares the results on a half circle with one calling closePath and the other not calling closePath:

Pop quiz

Q1. Do we need to use the closePath function on the shape we are drawing if we just want to fill the color and not draw the outline stroke?

  1. Yes, we need to use the closePath function.
  2. No, it does not matter whether we use the closePath function.

Wrapping the circle drawing in a function

Drawing a circle is a common function that we will use a lot. It is better to create a function to draw a circle now instead of entering several code lines.