This is the first of a series of canvas notes to study and review. See Canvas Core Technologies for the full notes

To learn canvas, we must first know how to draw line segments, and then realize complex graphics through many simple line segments, such as common charts, bar charts, line charts, etc., which are realized by line segments one by one.

Basic knowledge of

Canvas does not have much basic knowledge, mainly mastering how to draw line segments, graphs, pictures, texts, etc. Canvas can be drawn in a browser, or a simple picture can be drawn on the Node server using Node-Canvas. This article only records how to draw in the browser, as for how to draw in the Node side, you can go to the relevant information.

To draw in the browser, define the Canvas element in THE HTML. The default width and height are 300 * 150 and can be set by width and height. Note that canvas element style width and canvas drawing width and height are not the same thing as canvas width and height.

<canvas id="canvas">
  <p>The current browser does not support Canvas, please upgrade your browser</p>
</canvas>
Copy the code

Before drawing, we need to obtain the 2d drawing context of the current canvas first, and then always draw by manipulating the context.

let canvas = document.querySelector('#canvas');
if(! canvas) {throw new Error('can not find canvas element');
}
// Note that 2d. Arguments must be lowercase;
// The 3d rendering context can be obtained by setting the parameter to webgl
let ctx = canvas.getContext('2d');
Copy the code

Note: The code snippet above will be ignored in subsequent examples and used directlyctxThe variable represents the 2D drawing context of the canvas.

Now take a look at the coordinate system in canvas 2d drawing. Currently, the upper left corner of canvas element is the coordinate origin (0,0), the horizontal right is the positive direction of X axis, and the vertical down is the positive direction of Y axis, as shown below. Coordinate systems can be translated, rotated, and scaled to create animations, which will be explained in detail in the animation knowledge section.

Line segment

When drawing a simple line segment, we usually set the style of the line segment first, such as color, line width, line endpoint style, etc. We set strokeStyle to set the global drawing style of CTX, which can be RGBA or legal hexadecimal color value, or gradient object, etc. The following code simply draws a red line segment of width 10 from (10,10) to (50,60).

ctx.strokeStyle = 'red';
ctx.lineWidth = 10;
ctx.moveTo(10.10);
ctx.lineTo(50.60);
ctx.stroke();
Copy the code

Let’s look at the methods and properties associated with drawing line segments,

Related attributes:

  • LineCap, which tells the browser how to draw the end of a line segment. The value can be one of three: butt, round, or square. The default is butt.
  • LineWidth, which determines the pixel width of the line segment. Must be non-negative, non-infinite, default is 1.0.
  • LineJoin, which determines how to draw the focus when two line segments intersect, takes effect only when the two line segments are in different directions. The value can be bevel, round, or miter. The default value is miter.
  • MiterLimit, which tells the browser how to draw a miter-form line segment focus only whenlineJoin='miter'The default value is 10.0.
  • LineDashOffset sets the dotted offset, default is 0.0.

Related methods:

  • BeginPath, reset the current path by clearing all subpaths in the current path. Normally called when drawing a closed graph.
  • ClosePath: displays the closure of a path. The method is used to close arcs and open paths created by curves or line segments.
  • MoveTo, moves the current drawing point to the specified coordinates.
  • LineTo, draws a line segment from a previous point to a specified coordinate point.
  • SetLineDash, the method used to set the dotted line, takes an array of parameters indicating the length of the drawn solid line and the length of the gap between the lines.

Try drawing the same line segment with different lineCap values

ctx.lineWidth = 10;
ctx.textAlign = 'center';
let colors = ['red'.'green'.'blue'];
let lineCaps = ['butt'.'round'.'square'];
for (let [index, lc] of lineCaps.entries()) {
  ctx.strokeStyle = colors[index]; // Set the color of the line segment
  ctx.lineCap = lc; / / set lineCap
  ctx.beginPath(); // Clear the current path
  ctx.moveTo(10.20 + 20 * index);
  ctx.lineTo(50.20 + 20 * index);
  ctx.stroke();
  ctx.fillText(lc, 80.25 + 20 * index);
}
Copy the code

As you can see from the above figure, if lineCap is set to round and square, the ends of the original segment will be added with a certain length, except that round is an arc style and square is a rectangle style. It should be noted that only one current path can exist at any time in the canvas drawing context. In order to draw different line segments, beginPath() must be called before each drawing to clear the current path and start a new path.

Try drawing styles at the focal points of two line segments with different lineJoin values

ctx.lineWidth = 20;
ctx.textAlign = 'center';
ctx.lineCap = 'butt';
let colors = ['red'.'green'.'blue'];
let lineJoins = ['bevel'.'round'.'miter'];
for (let [index, lj] of lineJoins.entries()) {
  ctx.strokeStyle = colors[index]; // Set the color of the line segment
  ctx.lineJoin = lj; / / set the lineJoin
  ctx.beginPath(); // Clear the current path
  ctx.moveTo(10 + 80 * index, 20);
  ctx.lineTo(50 + 80 * index, 20);
  ctx.lineTo(50 + 80 * index, 60);
  ctx.stroke();
  ctx.fillText(lj, 40 + 80 * index, 80);
}
Copy the code

It can be seen that the three linejoins handle the differences at the focal points of the two line segments. When lineJoin is set to “miter”, the miterLimit attribute can be used to set the maximum ratio between the length of the inclined cable and the width of one half line. When the ratio exceeds this value, lineJoin adopts beVEL mode.

Canvas can draw not only solid lines, but also dotted lines. Draw a dotted line by setting the lineDashOffset property and calling setLineDash().

ctx.lineWidth = 10;
ctx.textAlign = 'center';
ctx.setLineDash([8.8]); // Represents the solid line part 8 pixels, the gap part 8 pixels
let colors = ['red'.'green'.'blue'];
let lineDashOffsets = [1.2.4];
for (let [index, ldOffset] of lineDashOffsets.entries()) {
  ctx.strokeStyle = colors[index]; // Line segment color
  ctx.lineDashOffset = ldOffset; // Set the offset
  ctx.beginPath();
  ctx.moveTo(10.20 + 20 * index);
  ctx.lineTo(100.20 + 20 * index);
  ctx.stroke();
  ctx.fillText(`lineDashOffset:${ldOffset}`.160.25 + 20 * index);
}
Copy the code

As you can see from the figure, lineDashOffset is the offset set to start drawing the dotted line. The setLineDash() method, which takes an odd number of array elements, makes a copy of the current array elements even by default. So you start with the 0th element, which is the length of the solid line, the first element, which is the length of the gap, the second element, which is the length of the solid line, the third element, which is the length of the gap, and if you get to the last element of the array, you start all over again, and so on.

ctx.lineWidth = 10;
ctx.textAlign = 'center';
let colors = ['red'.'green'.'blue'.'gray'];
let lineDashes = [[20.20], [40.40], [20.40], [20.40.20]].for (let [index, ld] of lineDashes.entries()) {
  ctx.strokeStyle = colors[index]; // Set the color
  ctx.setLineDash(ld); / / set lineDash
  ctx.beginPath();
  ctx.moveTo(10.20 + 20 * index);
  ctx.lineTo(171.20 + 20 * index);
  ctx.stroke();
  ctx.fillText(`lineDashes:[${ld}] `.240.25 + 20 * index);
}
Copy the code

Ant lines can be implemented by dynamically setting lineDashOffset, such as selecting ant lines at the edge of a selection in Photoshop.

let lineDashOffset = 0; / / the initial lineDashOffset
ctx.strokeStyle = 'green';
function animate() {
  if (lineDashOffset > 25) {
    lineDashOffset = 0;
  }
  ctx.clearRect(0.0, width, height); // Clear the current canvas
  ctx.lineDashOffset = -lineDashOffset; / / set lineDashOffset
  ctx.setLineDash([4.4]); // Set the solid line length and the gap length
  ctx.rect(20.20.100.100); // Draw a rectangle
  ctx.stroke(); // Stroke the canvas's current path
  lineDashOffset += 1; //lineDashOffset offset + 1
  window.requestAnimationFrame(animate); // Execute the animate function repeatedly with the browser frame rate
}
animate();
Copy the code

summary

When drawing line segments, it is necessary to understand the concept of canvas current path. At a certain moment, there is only one current path in canvas. BeginPath () must be called when starting a new path. You can set lineWidth, lineCap, and lineJoin to set the drawing style of the line segment. When tracing a line segment, you can use strokeStyle to set the color of the segment.

Not only solid lines can be drawn on canvas, but dotted lines can also be drawn using lineDashOffset and setLineDash().