JavaScript Canvas Stroke Properties
Written by Ian Elliot   
Monday, 10 February 2020
Article Index
JavaScript Canvas Stroke Properties
Dashes

The problem with miter joins is that for lines that meet at very sharp angles the miter can be very long – often longer than the lines themselves. To keep this under control there is another drawing context property you can set, miterLimit. This sets the maximum distance between the inner and outer corners if the miter was drawn. The default is 10 and if the miter is longer than this it isn’t drawn and a bevel is used:

 corner4

This raises the question, what is a bevel? It simply draws a line between the two outer corners of the lines and fills in the triangle:

corner5

Finally round draws a disc centered on the common endpoint with a radius equal to the thickness of the lines.

 corner6

For example:

var path1 = new Path2D();
path1.moveTo(100, 300);
path1.lineTo(500, 300);
path1.lineTo(100, 350);
ctx.lineJoin = "miter";
ctx.lineWidth = 10;
ctx.miterLimit = 100;
ctx.stroke(path1);

draws:

 corner7

If you set miterLimit to 10 the result is:

corner8

If you set lineJoin to bevel you get the same result:

var path1 = new Path2D();
path1.moveTo(100, 300);
path1.lineTo(500, 300);
path1.lineTo(100, 350);
ctx.lineJoin = "bevel";
ctx.lineWidth = 10;
ctx.stroke(path1);

corner9

Changing lineJoin to “round”

ctx.lineJoin = "round";

gives the following result:

corner10

The final way we can control the way a path is stroked is to set a dash pattern using the setLineDash function. This accepts an array that specifies how long the dash and spaces should be in co-ordinate units. For example, [4,8] sets a dash 4 units long followed by an 8 unit space. If you specify an odd number of elements in the array, the array is doubled in length to make it even. For example, [4,8,2] becomes [4,8,2,4,8,2]. You can also specify the current dash array using the getLineDash function. To set the line back to solid use an empty array:

ctx.setLineDash([]);

There is one last control you can use, the lineDashOffset. This starts the dash pattern at the co-ordinate given by the offset. Notice that the offset is relative to the dash pattern and just indicates where to start the pattern.

For example:

var path1 = new Path2D();        
path1.moveTo(0, 50);
path1.lineTo(300, 50);
ctx.setLineDash([4, 16]);
ctx.stroke(path1);

draws a line with dashes of 4 pixels followed by a 16-pixel space.

dash1

If we set the offset to 4 then the pattern starts with the 16-pixel space. If we set it to 2 then the pattern starts halfway though the first 4-pixel dash:

dash2

Although we have yet to deal with animation, the “marching ants” program is too good to miss. All that happens is that you animate a line by changing the dash offset by one each time. For example:

var ctx = document.body.
  appendChild(createCanvas(600, 600)).getContext("2d");
var path1 = new Path2D();
path1.rect(0, 50, 200, 200);
var offset = 0;
ctx.setLineDash([4, 2]);
function march() {            
     offset = (offset+1) % 16;
     ctx.clearRect(0, 0, ctx.canvas.width, 
ctx.canvas.height); ctx.lineDashOffset = offset; ctx.stroke(path1); requestAnimationFrame(march); } march();

This repeatedly draws the dashed line after changing the offset by one. The effect is very good for so little effort. See the live listing for a demo.

In chapter but not in this extract:

  • Antialiasing
  • Fill, Stroke and the Painter’s Algorithm
  • Holes and Fill
  • Gradient Fills
  • Pattern Fills

Summary

  • The stroke function simply colors the outline of the path, whereas fill colors all of the points in the interior of the path.

  • Color can be specified by name, RGB components or HSL.

  • Alpha values control the transparency of the color, with 1.0 being opaque and 0.0 being completely transparent.

  • For stroke you can set the lineWidth, lineCap, lineJoin and lineDash.

  • Anti-aliasing makes drawing look smoother, but it can cause unexpected results for small details. It cannot be disabled.

  • The simplest way of combining old and new colors is the painter’s algorithm, which allows the latest color to cover up the old.

  • Determining what is a “hole” in a closed path is difficult. There are two general rules, odd-even and non-zero winding, and they are both valid ways of defining a hole.

  • As well as solid color fills, you can also use linear gradient and radial gradient fills.

  • Pattern fills allow you to use any bitmap as a sort of “wallpaper” for the interior of paths.

 

 corner6

 

 

Now available as a paperback or ebook from Amazon.

JavaScript Bitmap Graphics
With Canvas

largecover360

 

Contents

  1. JavaScript Graphics
  2. Getting Started With Canvas
  3. Drawing Paths
      Extract: Basic Paths
      Extract: SVG Paths
      Extract: Bezier Curves
  4. Stroke and Fill
      Extract: Stroke Properties 
      Extract: Fill and Holes
      Extract: Gradient & Pattern Fills
  5. Transformations
      Extract: Transformations
      Extract: Custom Coordinates 
      Extract  Graphics State
  6. Text
      Extract: Text, Typography & SVG 
      Extract: Unicode
  7. Clipping, Compositing and Effects
      Extract: Clipping & Basic Compositing
  8. Generating Bitmaps
      Extract:  Introduction To Bitmaps
      Extract :  Animation 
  9. WebWorkers & OffscreenCanvas
      Extract: Web Workers
      Extract: OffscreenCanvas
  10. Bit Manipulation In JavaScript
      Extract: Bit Manipulation
  11. Typed Arrays
      Extract: Typed Arrays 
  12. Files, blobs, URLs & Fetch
      Extract: Blobs & Files
      Extract: Read/Writing Local Files
      Extract: Fetch API **NEW!
  13. Image Processing
      Extract: ImageData
      Extract:The Filter API
  14. 3D WebGL
      Extract: WebGL 3D
  15. 2D WebGL
    Extract: WebGL Convolutions

<ASIN:B07XJQDS4Z>

<ASIN:1871962579>

<ASIN:1871962560>

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

espbook

 

Comments




or email your comment to: comments@i-programmer.info



Last Updated ( Monday, 10 February 2020 )