Understanding Canvas lineJoin and miterLimit

Understanding Canvas lineJoin and miterLimit

The relationship of miterLength, lineWidth and internal angle

·

4 min read

When we draw two lines that are connected together, we take for granted that the join will look 'normal'.

However....

Joining two lines is not really that straight forward and in fact the Canvas API helps us out by making some sensible default decisions on how two joined lines should appear.

Looking at the image above, the red and blue lines represent what two lines look like if they are only joined by their coordinates and there have been no additional calculations made about how the remaining part of the lines should be joined. The internal meeting point of the two lines does not need any thought as naturally the 'inside' strokes of a line will always meet. The outside strokes of the red and blue lines however, do not meet. Our joined lines would look strange if left like this.

Let's first take a look at the lineJoin property.


lineJoin

The lineJoin property sets how two lines are joined. There are three different values which can be used: round, bevel and miter. If we do not set this property then the default value of miter is used.

lineJoin = 'type'

round -- draws a rounded arc with radius of half the lineWidth at the outside edge of two joined lines (top line in demo below)

bevel -- creates a flat edge at the outside edge of two joined lines (middle line in demo)

miter -- creates a single joint point at the outside edge of two joined lines (bottom line in demo)

The demo shows that we have drawn three lines which are each comprised of two adjoining lines. Each of these lines has used one of the lineJoin types to create a different kind of join. We have also added a reference line which has been constructed from two non-joined lines. The reference line shows how two non-joined lines that are drawn in the same way as joined lines will appear as though they do not have a correctly joined outside edge.

Try turning line 1 into a non-joined line by adding ctx.moveTo(150,75)immediately after the code ctx.lineTo(150,75)


miterLimit

When using lineJoin = 'miter', as the interal angle gets smaller the position at which the 'outside' line strokes and therefore the distance between the inside join point and the outside join point grows exponentially. This distance between the natural common joint point of the 'inside' strokes and the 'outside' strokes is called the miterlength.

As our internal angle gets smaller and smaller, the miterlength starts to become very long. This could start to cause unintended consequences as potentially our lines could appear to become very long.

The Canvas API solves this problem by using a miterLimit which governs how long the miterlength can be before it simply renders the line join as a bevel. The default value for the miterLimit is 10, but we can set our own value as follows:

miterLimit = value

where

miterLimit = max miterLength / lineWidth

The demo below shows how setting miterLimit = 2.3 will create a bevel for all of the joined lines except the last 'V' which is unaffected by the miterLimit value of 2.3.

In the demo, we have drawn four 'V' shapes using two connecting lines. The miterLimit is set as 2.3 and the lineWidth of each of the lines is 10. This means that for any joined lines a miterLength of over 23 points will be rendered as a bevel.

In the case of the last 'V', the miterLength is exactly 23 and so is unaffected by a miterLimit of 2.3. However, if we change the value of the miterLimit to 2.2, then the last 'V' will also be rendered as a bevel lineJoin.

It is worth noting that the position of the bevel join is always the same and is not affected by the miterLimit. The miterLimit purely determines whether a bevel join should be used instead of a miter join.

Try changing the miterLimit to the values of 3.2, 4.0 and 5.1

I have to put my pen down now. 🤸‍♂️