简体   繁体   中英

Converting a list of points to an SVG cubic piecewise Bezier curve

I have a list of points and want to connect them as smoothly as possible. I have a function that I evaluate to get these points. I could simply use more sampling points but that would only increase the SVG file size. I think using a piecewise cubic Bezier curve would be better suited. How do I do this?

I did some research and came across the svgpathtools package, which looked promising. However, I did not find any functionality like this.

If you ever used Illustrator you certainly remember that the first control points of a bezier is connected with the last control point of the previous one. This line is tangent to the curve. In my code I am using the size of this line to draw the curve.

Also: the first & the last curve are quadratic Bezier (only one control point). All the other curves are cubic Bezier (2 control points).

 // size of the tangent var t = 1 / 5; // points array var p = [{ x: 100, y: 100 }, { x: 250, y: 150 }, { x: 300, y: 300 }, { x: 450, y: 250 }, { x: 510, y: 140 }, { x: 590, y: 250 }, { x: 670, y: 140 }]; function controlPoints(p) { // given the points array p calculate the control points for the cubic Bezier curves var pc = []; for (var i = 1; i < p.length - 1; i++) { var dx = p[i - 1].x - p[i + 1].x; // difference x var dy = p[i - 1].y - p[i + 1].y; // difference y // the first control point var x1 = p[i].x - dx * t; var y1 = p[i].y - dy * t; var o1 = { x: x1, y: y1 }; // the second control point var x2 = p[i].x + dx * t; var y2 = p[i].y + dy * t; var o2 = { x: x2, y: y2 }; // building the control points array pc[i] = []; pc[i].push(o1); pc[i].push(o2); } return pc; } function drawCurve(p) { var pc = controlPoints(p); // the control points array let d =`M${p[0].x},${p[0].y} Q${pc[1][1].x},${pc[1][1].y}, ${p[1].x},${p[1].y} ` if (p.length > 2) { // central curves are cubic Bezier for (var i = 1; i < p.length - 2; i++) { d += `C${pc[i][0].x}, ${pc[i][0].y}, ${pc[i + 1][1].x}, ${pc[i + 1][1].y}, ${p[i + 1].x},${p[i + 1].y}`; } // the first & the last curve are quadratic Bezier var n = p.length - 1; d+= `Q${pc[n - 1][0].x}, ${pc[n - 1][0].y}, ${p[n].x}, ${p[n].y}`; } return d } thePath.setAttribute("d", drawCurve(p))
 svg{border:solid; fill:none;stroke:black;}
 <svg id = 'svg' viewBox="0 0 800 400"> <path id="thePath" /> </svg>

This is a pen where I'm doing the same in canvas https://codepen.io/enxaneta/pen/PqLNLv . Here you can see the tangents.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM