Skip to content

Instantly share code, notes, and snippets.

@jashmenn

jashmenn/generatePath.js

Last active Mar 6, 2020
Embed
What would you like to do?
Deconstruction of the curves on @Wattenberger's Thinking in Hooks Post
// 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
You can’t perform that action at this time.