preface

Early browsers did not provide 2D drawing, and many of the applications used for drawing were done in Flash. With the popularity of HTML5 standard, SVG/Canvas basically does not have compatibility problems in browsers. In Node, small program environment can also use Canvas drawing.

A variety of applications based on 2D graphics are also emerging, such as visualization libraries such as Echarts, G2, processon’s flowcharts, and even Google Docs has moved to Canvas. This paper introduces the basic knowledge of 2D drawing and some performance optimization methods.

Basic technology

At present, the common underlying technologies used for Web 2D drawing are mainly Canvas and SVG, and most 2D rendering engines are based on these two technologies, such as Zrender, Paperjs and raphael.js. Webgl is mainly used for 3D rendering, 2d is a special case of 3D, so WebGL can also be used to draw 2D graphics, such as PixiJS.

Each of these technologies has its own advantages and disadvantages. Generally speaking, canvas/ SVG is not a big use for static scenes such as chart library and graph visualization. In scenes with a large amount of data or animation, using Canvas has more advantages in performance. In addition to its performance advantages, WebGL can do a lot of special effects that Canvas/SVG does not.

svg

SVG is an XML-based 2D vector drawing technology that is resolution-independent and does not blur when scaling. In addition to providing basic graphics, SVG comes with built-in animations and rich filter elements. Since SVG is DOM-based, it also works well with react, Vue and other frameworks.

<svg width= 300  height= 300 >
    <circle cx= 50  cy= 50  r= 10  fill= #000  stroke= red  stroke-width= 1  />
</svg>
Copy the code

canvas

Canvas Canvas is a new element in HTML5 that provides a drawing interface. Compared with SVG, Canvas has a more flexible grasp of pixels, and without DOM, it has better performance for rendering massive data than SVG.

Const CTX = Canvas.getContext ('2d') ctx.beginPath() ctx.arc(50, 50, 10, 0, Math.PI * 2) ctx.fillStyle = '#000' ctx.strokeStyle = 'red' ctx.fill() ctx.stroke()Copy the code

webgl

Drawing 2D graphics using WebGL Is usually done by triangling 2d graphics and using WebGL to draw triangles. It is easier to triangulate simple geometric shapes such as lines, circles and rectangles, but more difficult to triangulate complex shapes, especially those with holes.

There is also a scheme based on SDF (directed distance field) to draw some common geometric shapes. In this scheme, the point is defined as positive outside the region boundary, 0 on the boundary and negative inside the boundary. Through the SDF function, you can determine whether the pixel is in the graph.

SDF of a circle

float myCircleSDF( in vec2 p, in float r ) 
{
    return length(p)-r;
}
Copy the code

Graphics rendering

In addition to directly providing common graphics elements such as rect, Circle, polygon, etc., SVG also provides a versatile PATH element that can draw any shape through the path directive. Canvas also provides API similar to PATH, which can be converted with SVG Path to achieve support of SVG/Canvas dual engine.

canvas svg path
moveTo m, M
lineTo L, l
beizerCurveTo c, C, S, s
quadraticCurveTo Q q T t
arc & ellipse A, a
closePath z, Z
rect

SVG Path draws a triangle

<path d= M 0,0L100,100L0,100Z  />
Copy the code

Using Canvas

Ctx.beginpath () ctx.moveto (0,0) ctx.lineto (100, 100) ctx.lineto (0, 100) ctx.closepath () ctx.beginPath() ctx.moveto (0,0) ctx.lineto (0, 100) ctx.closepath ()Copy the code

In addition, modern browsers support drawing paths using Path2D objects

Const path = new Path2D('M 0,0L100,100L0,100Z'); ctx.fill(path);Copy the code

Event interaction

If you use SVG drawing technology, you can listen for events just like normal DOM elements. However, canvas only provides a canvas, and the graph where the event coordinates are located cannot be directly obtained. Users need to judge the pick up by themselves. Common pick up methods include geometric pick up and pixel pick up. In addition, Canvas 2D provides the isPointInPathapi to determine whether a point is in a path.

Geometry to pick up

Geometric picking is directly based on mathematical methods to determine whether the coordinates of points are in the graph. For example, if the point is inside the circle, you can calculate whether the distance from the point to the center of the circle is less than the radius of the circle.

function isPointInCirlce(cx, cy, r, x, y) {
    return (x -cx ) ** 2 + (y - cy) ** 2 < r ** 2
}
Copy the code

For most simple shapes, it can be calculated mathematically, and the performance is the best of all methods. For complex shapes, especially those containing curves, the math is also difficult.

Pixels to pick up

The realization principle of pixel pick is relatively simple. All graphics are redrawn on the off-screen canvas, and the index color is generated using the graphic number during drawing. Then use the getImageData provided by canvas to obtain the color at (x, y), so as to obtain the graph corresponding to this point. Due to the re-drawing of the graph, when there are many graphs, the drawing overhead is large, and the performance is not as good as that of pure geometric pickup.

OKee uses a combination of the above two pickup methods in practice. For most simple shapes, use math. Unable to use mathematically calculated complex shapes, then use pixel pick. The overall pickup performance can support interactions of hundreds of thousands of pixels.

animation

Animation is based on the visual retention effect of human eyes, by changing the position of graphics, color and other attributes, the formation of animation effect. The browser provides the requestAnimationFrame interface, which is used to draw the next frame.

According to the different dynamic effects, the animation is divided into the following two categories

  • Properties animation, position, rotation, color and other properties for interpolation
  • Path animation, moving along a path

  • Morphing animation, shape changes over time

Animation interpolation used by the easing function, you can refer to tween. js provided, such as quadratic function, cubic curve.

Performance optimization

Rendering performance optimization

  • Minimize canvas context calls, such as setting the context only once for a graph of the same style
Ctx.save () ctx.strokestyle = color ctx.lineWidth = 1 for (let I = 0; i < 1000; i++) { ctx.strokeRect(x, y, width, height) } ctx.restoreCopy the code
  • Graphics outside the viewport are not involved in drawing

There are many scenes where only part of the elements are visible, and elements that are not visible outside the viewport can be skipped

  • Draw only the parts that change (dirty Rectangle technique)

When a change in an element on the screen is confined to a single area, you can erase the pixels in that area and redraw the graphics that overlap with that area instead of redrawing it in full screen.

  • Layered rendering or use of invariant and variable graphicscacheAsBitMapCaching technology
  • Large amounts of data are rendered in multiple frames

For example, a large number of scatter points in a diagram can wait several seconds to draw if rendered simultaneously. You can render a portion of each frame until all graphics are drawn.

  • Use multi-threading and off-screen canvas tiles for rendering

Canvas is divided into multiple tiles, and then rendered to the corresponding tile area by using The Screen Canvas in multiple work threads. This optimization method is quite common in map applications, and map data itself is stored in the form of tiles.

Pick performance optimization

  • Use a bounding box to speed up judgment

First judge whether the point is in its bounding box, if not, then directly exclude. If so, more precise geometry or pixel pick judgments are used.

  • Cache graph transformation matrix, inverse matrix

In the process of picking up, the matrix and inverse matrix of the graph need to be computed repeatedly. Caching reduces the amount of computation.

  • Spatial indexes such as R-tree are used to speed up the picking process

Space is used to exchange time, and r-tree index is established to speed up the pickup process.

About us

Founded in 2019, OKee Design aims to create a Design system with clear logic and strong scalability for enterprise-level product Design with various scenarios and complex demands. Through enough comprehensive, universal, beautiful, flexible content, to provide strong solutions and guidelines for all kinds of product design.

Github organization: github.com/oceanengine

reference

  • Zrender: github.com/ecomfe/zren…
  • Pixijs: github.com/pixijs/pixi…
  • Raphaeljs: github.com/DmitryBaran…
  • Path2D: developer.mozilla.org/zh-CN/docs/…
  • MDN Canvas 2D context
  • Canvas pick scheme selection
  • Bessel curve correlation algorithm
  • Ray method
  • glMatrix
  • tween.js
  • Show list with dirty rectangle render
  • 2D Basic graphics SDF(Directed Distance Field)