preface

In the development of specific projects, we often use Canvas to draw charts, rich graphics, animation interaction and other application scenarios. This article summarizes what I know about Canvas development and common problems I may encounter. The basics and common API usage are for you to learn on your own and will not be repeated here.

Important concepts

The HTML5 < Canvas > element is used for drawing graphics, which must be completed through JS scripts to generate graphics containers. Canvas API document Canvas.width /height: Used to control the width and height of the canvas canvas drawing area. Set according to the actual screen environment, otherwise the drawing will be distorted. Canvas.getcontext () : Returns the drawing context of the canvas, on which the actual drawing depends. Canvas.toblob () : Creates Blob objects for a Canvas image. Canvas.todataurl () : Returns base64 data image data.

<canvas>The label

The < Canvas > tag in HTML5 only generates the graph container, and the graph drawing must be done through JS scripts.

Canvas width height and CSS width height

<canvas width="600" height="300" style="width: 300px; height: 150px"></canvas>
Copy the code
  • Width /height in style represents the width/height occupied by the canvas element on the interface, namely the CSS width and height on the style.
  • The width/ Height ** property represents the actual width and height of the Canvas pixel. ** to control the width and height of the Canvas drawing area. If the width and height are not set, the default width and height will be set (300*150). It is generally recommended to set the drawing area of the graph width and height limit.

When using the Canvas API to draw graphics, the coordinates and size used are based on the Canvas width and height property, and have nothing to do with the CSS style width and height. The width and height of CSS determines the visual display size of canvas graphics. The width and height of canvas canvas will be scaled to the width and height of CSS.

In practical use, try to avoid this due to the size of the inconsistent scale rendering, resulting in fuzzy graphics, serrations and other problems.

Drawing context

Canvas.getcontext () : Returns the drawing context of the canvas, on which the actual drawing depends. This article focuses on two-dimensional drawing :const Context = ‘ ‘Canvas.getContext (‘ 2D ‘);

The drawing process of each path is based on the current state of the drawing context when the actual canvas is drawn. The drawing process is the equivalent of painting with only one brush, and the drawing points, colors, and so on for each path are based on the current state of the drawing context (position, color, thickness, etc.). For noncontinuous path drawing, the drawing process is declared with context.beginPath() so that the drawing style is not overridden.

Such as:

context.strokeStyle = 'blue';
context.moveTo(10.10);
context.lineTo(100.10);
context.stroke();

context.strokeStyle = 'red';
context.moveTo(100.10);
context.lineTo(10.50);
context.stroke();
Copy the code

The style is overwritten and the drawing effect is as follows:



withcontext.beginPath()Declare path, code:

context.beginPath();
context.strokeStyle = 'blue';
context.moveTo(10.10);
context.lineTo(100.10);
context.stroke();

context.beginPath();
context.strokeStyle = 'red';
context.moveTo(100.10);
context.lineTo(10.50);
context.stroke();
Copy the code

Then the styles of the two lines are not affected, and the drawing effect is as follows:

context.canvas

This is useful in many cases where you need to get information about the current canvas while drawing. CanvasRenderingContext2D. Canvas is a read-only property, can return to the current context from which the < canvas > element, and obtain the attribute information such as the width/height of the canvas.

context.clearRect()

In actual development, often used in the API, to clear the drawn area, otherwise repeated drawing in the same area will occur graphics overlay.

Canvas vs. SVG

Canvas and SVG are currently the main graphics rendering technologies used in HTML5. The former provides Canvas tag and drawing API, while the latter is a complete set of independent vector graphics language that uses XML format to define images.

  1. Canvas uses JS to draw graphics, only as an HTML element; SVG, on the other hand, uses an XML format to define graphics, and the resulting graphics contain a variety of graphics elements (Path, Line, Rect).
  2. Canvas drawing is based on pixel-level control; SVG is based on internal graphical element operation control;
  3. Canvas is pixel-level rendering and depends on resolution; SVG is a vector graphics that does not distort the quality of the graphics when scaled.
  4. Event interaction: Events can only be registered to the Canvas<canvas>On the label, but through event delegate, the interaction can be refined down to pixel points (x,y); SVG, on the other hand, can attach a separate JavaScript event handler to an element, but can only control refinement on graphic elements.
  5. Canvas is suitable for small area and big data application scenarios. SVG is suitable for large area, small number of applications (few image elements).

Canvas applicable scenarios: suitable for pixel processing, dynamic rendering and large data volume rendering; Suitable for graphics-intensive games; Application scenarios of SVG: It is suitable for static image display, high-fidelity document viewing and printing.

Q&A

Drawing canvas on mobile terminal is fuzzy

The phenomenon of

The diagram below:



In the picture above, the canvas scale component drawn on iPhone 6S model is blurred and distorted when it is not processed by mobile terminal. Graphics quality can be guaranteed after compatibility processing.

The above calibration components refer to another of my articles, address:”Draws a configurable scale component using Canvas”

why

Regarding mobile hd screen DPR, picture blur, mobile terminal adaptation and other issues, unclear children’s shoes can refer to “About mobile terminal adaptation, you must know” this article, more detailed. Without further elaboration, this article will only deal with Canvas ambiguity on mobile. On the hd screen of mobile terminal, the problem of Canvas blur is often encountered. It’s essentially the same as the blur problem on mobile. The image drawn by Canvas is also a bitmap. On the screen with DPR > 1, one pixel of the bitmap may be rendered by multiple physical pixels. However, these physical pixels cannot be accurately assigned the color corresponding to the bitmap pixel, and only approximate values can be taken, so the screen with DPR > 1 will be blurred. When drawing canvas graphics on THE PC side, we will directly treat 1 Canvas pixel as 1px CSS pixel. This is no problem, because the DPR of PC screen is 1. This can’t be done directly on mobile screens with DPR > 1.

To solve

The solution, of course, starts with DPR.

  1. throughwindow.devicePixelRatioGet the DPR of the current device screen;
  2. First get or set the width and height of the Canvas container;
  3. Set the width and height attributes of the Canvas element according to DPR; indpr = 2Is equivalent to expanding the canvas 2 times;
  4. throughcontext.scale(dpr, dpr)Scale the frame of the Canvas. indpr = 2In this way, the drawing scale is enlarged by 2 times. Then the actual drawing pixel of canvas can be processed according to the original pixel value.

When rendered to the screen, the enlarged canvas graphic is rendered to the Canvas container in equal scale. To ensure the quality of canvas graphics.

/ / get the DPR
const dpr = window.devicePixelRatio; 
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Get the width and height of the Canvas container
const { width: cssWidth, height: cssHeight } = canvas.getBoundingClientRect();
// Set Canvas width and height according to DPR, so that 1 Canvas pixel is equal to 1 physical pixel
canvas.width = dpr * cssWidth;
canvas.height = dpr * cssHeight;
// Set the canvas element width and height attributes according to DPR
ctx.scale(dpr,dpr);
Copy the code

Canvas drawImage() parameter problem, mobile image blur problem

Canvas’s drawImage() function has a particularly confusing aspect. Its 5 and 9 arguments are used in different argument positions. Not paying attention to this in actual development can leave you particularly confused as to what the problem is! Sweat!

One of the quirks of the drawImage() method is that the position of the parameters is different between the 5 and 9 arguments. This is different from the normal API. Generally API optional parameters are placed behind. However, when drawImage() uses nine arguments, the optional arguments sx, sy, sWidth and sHeight are first. If you don’t pay attention to this, some behaviors will be incomprehensible.

And the image inserted by the drawImage() function will also have the problem of image blur on the mobile DPR >1 screen. When the mobile terminal loads another drawn Canvas element through drawImage(), it should also pay attention to the compatibility processing of the other Canvas element and the difference of coordinate system between the two.

// Set the width and height of canvas_bg
canvas_bg.width = (config.unit * (scale_len - 1) + config.width) * dpr; canvas_bg.height = config.height * dpr; ctx_bg.scale(dpr, dpr); .// Initialize the start position
point_x = (config.def - config.start) / config.capacity * config.unit;
// On the main canvas CTX, insert another canvas_bg canvas by drawImage();
ctx.drawImage(canvas_bg, point_x * dpr, 0, config.width * dpr, config.height * dpr, 0.0, config.width, config.height);

Copy the code

In the above code, the canvas_bg canvas also needs to deal with the canvas blur problem mentioned above; On the main canvas CTX, when another canvas_bg canvas graph is inserted by drawImage(), it is necessary to pay attention to the difference in the proportion of coordinate system between the two. At this time, the coordinate system of Canvas_bg is scaled according to DPR.

When the size of Canvas drawing size or drawImage inserting image or getImageDate obtaining graphic resources is larger than a certain threshold, the problem of drawing blank may occur.

In the actual development, when the size of Canvas drawing size or drawImage inserting image and getImageDate obtaining graphics resource is greater than a certain threshold, the rendered picture is blank. The exact threshold is uncertain, depending on the runtime environment. But this should also be a potential flare for drawImage drawing.

For example, in the picture below, the scale canvas drawn is too large, and it is cut and rendered on the main canvas. The whole scale is blank, but the interaction is not affected.

Canvas getImageData cross-domain problem

As long as cross-domain images can be displayed normally in a web page, they can be drawn using canvas’s drawImage() API. However, if you want to obtain the complete pixel information of the picture through the getImageData() method, it is likely that cross-domain problems will occur when converting the local output.

Solution:

1. Enable the page and server to cross-domain. 2. To enable cross-domain Settings for images, 'img.setattribute ('crossOrigin', 'anonymous'); `Copy the code