Cover by Jeff Fulton, Steve Fulton

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

O'Reilly logo

Using Paths to Create Lines

Paths are a method we can use to draw any shape on the canvas. A path is simply a list of points, and lines to be drawn between those points. A Canvas context can only have a single “current” path, which is not stored as part of the current drawing state when the context.save() method is called.

Context for paths is a critical concept to understand, because it will enable you to transform only the current path on the canvas.

Starting and Ending a Path

The beginPath() function call starts a path, and the closePath() function call ends the path. When you connect two points inside a path, it is referred to as a subpath. A subpath is considered “closed” if the final point connects to the first point.

Note

The current transformation matrix will affect everything drawn in this path. As we will see when we explore the upcoming section on transformations, we will always want to set the transformation matrix to the identity (or reset) if we do not want any transformation applied to a path.

The Actual Drawing

The most basic path is controlled by a series of moveTo() and lineTo() commands, as shown in Example 2-2.

Example 2-2. A simple line path

function drawScreen() {
   context.strokeStyle  = "black"; //need list of available colors
   context.lineWidth  = 10;
   context.lineCap  = 'square';
   context.beginPath();
   context.moveTo(20, 0);
   context.lineTo(100, 0);
   context.stroke();
   context.closePath();

}

Figure 2-2 shows an example of this output.

A simple line path

Figure 2-2. A simple line path

Example 2-2 simply draws a 10-pixel-wide horizontal line (or stroke) from position 20,0 to position 100,0.

We have also added the lineCap and strokeStyle attributes. Let’s take a brief look at the various attributes we can apply to a line before we move on to some more advanced drawing.

lineCap attributes

context.lineCap

The lineCap is the end of a line drawn on the context. It can be one of three values:

butt

The default; a flat edge that is perpendicular to the edge of the line.

round

A semicircle that will have a diameter that is the length of the line.

square

A rectangle with the length of the line width and the width of half the line width placed flat perpendicular to the edge of the line.

lineJoin attributes

context.lineJoin

The lineJoin is the “corner” that is created when two lines meet. This is called a join. A filled triangle is created at the join, and we can set its basic properties with the lineJoin Canvas attribute.

miter

The default; an edge is drawn at the join. The miterLimit is the maximum allowed ratio of miter length to line width (the default is 10).

bevel

A diagonal edge is drawn at the join.

round

A round edge is drawn at the join.

lineWidth

The lineWidth (default = 1.0) depicts the thickness of the line.

strokeStyle

The strokeStyle defines the color or style that will be used for lines and around shapes (as we saw with the simple rectangles in Example 2-2).

Examples of More Advanced Line Drawing

Example 2-3 shows these attributes in action; the results are depicted in Figure 2-3. There are a few oddities when drawing lines on the canvas, which we will point out along the way.

Example 2-3. Line cap and join

function drawScreen() {

      // Sample 1: round end, bevel join, at top left of canvas
      context.strokeStyle  = "black"; //need list of available colors
      context.lineWidth  = 10;
      context.lineJoin  = 'bevel';
      context.lineCap  = 'round';
      context.beginPath();
      context.moveTo(0, 0);
      context.lineTo(25, 0);
      context.lineTo(25,25);
      context.stroke();
      context.closePath();

      // Sample 2: round end, bevel join, not at top or left of canvas
      context.beginPath();
      context.moveTo(10, 50);
      context.lineTo(35, 50);
      context.lineTo(35,75);
      context.stroke();
      context.closePath();

      // Sample 3: flat end, round join, not at top or left of canvas
      context.lineJoin  = 'round';
      context.lineCap = 'butt';
      context.beginPath();
      context.moveTo(10, 100);
      context.lineTo(35, 100);
      context.lineTo(35,125);
      context.stroke();
      context.closePath();

   }
Line cap and join

Figure 2-3. Line cap and join

These three line and join samples should help illustrate some of the combinations of attributes we can use to draw paths on the canvas.

The first sample attempts to draw starting at the top left of the canvas, resulting in a strange image. Canvas paths are drawn outward in both the x and y directions from the center of the pixel it begins on. For this reason, the top line in Sample 1 seems to be thinner than the 10 pixels we specified. In addition, the “round” end of the top-left horizontal line segment cannot be seen because both of these were drawn off the screen in the “negative” value areas of the screen coordinates. Furthermore, the diagonal “bevel” at the lineJoin is not drawn.

Sample 2 rectifies the problems in Sample 1 by offsetting the beginning of the drawing away from the top left. This allows the entire horizontal line to be drawn, as well as the “round” lineCap and the “bevel” lineJoin.

Sample 3 shows us eliminating the extra lineCap in favor of the default “butt,” and changing the lineJoin to “round.”

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required