The tool uses dat.gui to create two variable input controls called sliceAngle and circleRatio.
sliceAngle defines how deep or shallow the scalloping of the circular arcs is
circleRatio controls the scale difference between the two circular arcs’ radii
These are the only two inputs necessary to define a Cyma curve. To constrain the size of the radii, a max constant is also defined.
The only really tricky bit was figuring out the math for the path commands for the first arc, specifically the radius. It needed to start where the first arc ended, while respecting the angle at which the path was moving (to get a smooth inflection point), while scaling apprioriately to the circleRatio proportions, while terminating at the right position on the canvas. Additionally, the input value of the ratio variable needed to be log-scaled to make it feel smooth.
It ended up looking something like this:
In JavaScript, the full draw function incorporating the formula above looks like the below. It takes the variables input by the user, and calculates and writes the new path command string to the SVG on-screen.
const cyma = document.getElementById('cyma')
// redraw svg on variable change
const draw = () => {
// largest possible circle radius
const max = 3000
// get length of first segment as a fraction of the total curve length
let lengthA = 1000 * variables.circleRatio
// get length of second remaining segment
let lengthB = 1000 - lengthA
// ellipse formula to log-scale the ratio and get radius of first curve
let radiusA = -1 * Math.sqrt((1 - Math.pow(variables.sliceAngle - 1, 2)) * Math.pow(max - (lengthA / 2), 2)) + max
// get radius of second curve proportionally
let radiusB = (lengthB / lengthA) * radiusA
// write svg path data using the arc directive
let path = `
M 500 0
A ${radiusA} ${radiusA} 0 0 1 500 ${lengthA}
A ${radiusB} ${radiusB} 0 0 0 500 1000`
// apply data to svg path (d) attribute
cyma.setAttribute('d', path)
}
Additionally, there are buttons to either download the current curve as an SVG file, or to copy the SVG code to the clipboard in a format that can be easily pasted into Figma.