In SVG, all graphics can be simulated using Path, and you can find an introductory tutorial at MDN.

Key points for plotting bezier curves

Start with the cubic Bezier curve, which requires a coordinate point and two control points, embodied in the label PATH, which is the D attribute

C x1 y1, x2 y2, x y (or c dx1 dy1, dx2 dy2, dx dy)

Where x and y are the final endpoint, x1, y1, x2, y2 are the coordinates of the two control points. This is a little abstract, so let’s do an example

This is a Bezier curve, which is generated by the path tag, and the d property is

M 162.5 338.5 C 165.5 230.5 301.5 223.5 290.5 292.5

Its starting point coordinates are (162.5, 338.5), M stands for move to, and the letter C after it stands for curve, which is a cubic Bezier curve. Can be seen as

C Control point 1(x, y) Control point 2(x, y) end point (x, y)

To draw the Bezier curve using the path tag, you only need to know the position of the coordinate points and corresponding control points

The data structure

In fact, the data structure here we only need to store coordinate points and control points, and some common attributes

function path{
  nodes: Node[],
  strokeWidth: number,
  stroke: string,
  fill: string
}

function node {
  anchorPoint: {
      x,
      y  // Anchor point coordinates
  },
  ctrPoint: {
      x,
      y // Control point coordinates}}Copy the code

A path consists of multiple anchors, so an array of anchors is added to the path structure to store the coordinates of the points

Rendering path

The work here is similar to the React VDOM. JavaScript is used to describe the path attribute and the location of each point, and the d attribute (a string of path) is obtained by calculation and rendered to the browser. Instead of directly manipulating DOM, maintenance and modification are more convenient

const d = nodes.reduce((pre, cur, index) = > {
	if (index === 0) {
   		pre += `M ${cur.anchorPoint.x} ${cur.anchorPoint.y} C ${cur.ctrPoint.x} ${cur.ctrPoint.y}`
     	} else {
        	pre += `${cur.ctrPoint.x} ${cur.ctrPoint.y} C ${cur.anchorPoint.x} ${cur.anchorPoint.y}`
        }
    return pre
}, "")
Copy the code

The coordinates of each point need to be combined into D attributes that can be recognized by the browser and then handed over to the browser to do the rendering

Multiple Bezier curves

In practice, there is rarely a single Bezier curve. For example, in photoShop, the pen tool can draw multiple bezier curves. Fortunately, the Path tag provides this functionality.

M 222.5 485.5 C 222.5 485.5 350.5 561.5 359.5 453.5 C 368.5 345.5 445.5 431.5 445.5 431.5

In fact, as long as the C command is continuously added, multi-segment Bezier curve can be drawn. It should be noted that the anchor point coordinates of the boundary point between the two CS are the same while the control point coordinates are symmetric about the anchor point center

The node data structure needs to be modified to add a second control point



function node {
  anchorPoint: {
      x,
      y  // Anchor point coordinates
  },
  ctrPoint: {
      x,
      y // Control point coordinates
  }
  ctr2Point: {
      x,
      y
  }
}

Copy the code

Let’s do the same thing for D

const d = nodes.reduce((pre, cur, index) = > {
	if (index === 0) {
   		pre += `M ${cur.anchorPoint.x} ${cur.anchorPoint.y} C ${cur.ctrPoint.x} ${cur.ctrPoint.y}` // Start node
     	} else if (index + 1 < nodes.length - 1) {
        	pre += `${nodes[i].ctrPosX} ${nodes[i].ctrPosY} ${nodes[i].posX} ${nodes[i].posY} C ${nodes[i].ctr2PosX} ${nodes[i].ctr2PosY} ` // Intermediate node
        }
        else {
        	pre += `${cur.ctrPoint.x} ${cur.ctrPoint.y} C ${cur.anchorPoint.x} ${cur.anchorPoint.y}` // End node
        }
    return pre
}, "")
Copy the code

This completes the drawing of multiple Bezier curves