Deconstruction of the curves on @Wattenberger's Thinking in Hooks Post
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This code is from: https://github.com/Wattenberger/Wattenberger-2019/blob/07024a820011988f5fbefed21161b1111f38e710/src/components/Blog/posts/Hooks/Hooks.jsx#L451-L470 | |
// It generates the SVG path for the curve between two lines on the post "Thinking in React Hooks", located here: https://wattenberger.com/blog/react-hooks | |
// | |
// It's a good idea to pull up the documentation on SVG paths here: https://www.w3.org/TR/SVG/paths.html | |
// | |
// As you may know, SVG paths are specified by a string where a | |
// letter is the "command" and the numbers following are the "arguments" | |
// | |
// We'll be using 4 commands: | |
// | |
// * M "moveto" - https://www.w3.org/TR/SVG/paths.html#PathDataMovetoCommands | |
// * L "lineto" - https://www.w3.org/TR/SVG/paths.html#PathDataLinetoCommands | |
// * C "curveto" - https://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands | |
// * Z "closepath" - https://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand | |
const lineHeight = 1 | |
const middleWidth = 1 | |
const curveAmount = 0.3 | |
const generatePath = (a, b) => { | |
// a is the line number of the code on the left side | |
// b is the line number of the code on the right side | |
return pointsToPath([ | |
// Move our cursor to the initial position | |
// The syntax of "moveto" is: | |
// M x y | |
// So here, `a` is the line number. | |
// We subtract 0.01 because... (? ask @wattenberger) | |
["M", 0, a * lineHeight - 0.01], | |
// Now we draw a line from the current point (where we moved to) to this new point. | |
// The syntax of "lineto" is: | |
// L x y | |
// You'll notice that we're drawing to the point we're already on - this has the effect of just starting the line. | |
// We start this line at the top-right (? ask @wattenberger) of line number `a` on the left side. | |
["L", 0, a * lineHeight - 0.01], | |
// Now we start a new curve. | |
// The syntax of curveto is: | |
// C x1 y1 x2 y2 x y | |
// For me, the easiest way to think of this is to start with a straight line. We're drawing a line between two points, | |
// but the catch is that a Bezier curve has *two control points*. | |
// The "implicit" argument here is the *current point*, which comes from the previous L command. | |
// The "line" we're drawing goes from the current point to x y (the last two arguments). | |
// The first four arguments are the x,y coordinates of the control points. | |
["C"], | |
// this gives us a control point that is towards the right at the line on the left side | |
[middleWidth * curveAmount, a * lineHeight - 0.01], | |
// the second control point is towards the opposite direction, at the hight of the right side | |
[middleWidth * (1 - curveAmount), b * lineHeight - 0.01], | |
// this is our "target" point on the right side | |
[middleWidth, b * lineHeight - 0.01], | |
// Now on the top (?) of the right side, we draw a straight line down (?) | |
// to the bottom of this line on the right sie | |
["L", middleWidth, (b + 1) * lineHeight + 0.01], | |
// Making a curve again! | |
// This is the "reverse" of the above process | |
["C"], | |
// Control point 1 for the right side | |
[middleWidth * (1 - curveAmount), (b + 1) * lineHeight + 0.01], | |
// Control point 2 for the left side | |
[middleWidth * curveAmount, (a + 1) * lineHeight + 0.01], | |
// Target point back on the left side | |
[0, (a + 1) * lineHeight + 0.01], | |
// Draw a straight line to our current position | |
// (Why? Ask @wattenberger) | |
["L", 0, (a + 1) * lineHeight + 0.01], | |
// Close the path | |
["Z"] | |
]); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment