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