Skip to content

Commit 0c7ab98

Browse files
committed
Back off smoothing when there's not enough space left
1 parent 24f2bb9 commit 0c7ab98

File tree

1 file changed

+17
-24
lines changed

1 file changed

+17
-24
lines changed

src/index.ts

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,11 @@ interface CornerPathParams {
208208
height: number
209209
}
210210

211+
// The article from figma's blog
212+
// https://www.figma.com/blog/desperately-seeking-squircles/
213+
//
214+
// The original code by MartinRGB
215+
// https://github.com/MartinRGB/Figma_Squircles_Approximation/blob/bf29714aab58c54329f3ca130ffa16d39a2ff08c/js/rounded-corners.js#L64
211216
function getPathParamsForCorner({
212217
cornerRadius,
213218
cornerSmoothing,
@@ -217,32 +222,20 @@ function getPathParamsForCorner({
217222
const maxRadius = Math.min(width, height) / 2
218223
cornerRadius = Math.min(cornerRadius, maxRadius)
219224

220-
// The article from figma's blog
221-
// https://www.figma.com/blog/desperately-seeking-squircles/
225+
// From figure 12.2 in the article
226+
// p = (1 + cornerSmoothing) * q
227+
// in this case q = R because theta = 90deg
222228
//
223-
// The original code
224-
// https://github.com/MartinRGB/Figma_Squircles_Approximation/blob/bf29714aab58c54329f3ca130ffa16d39a2ff08c/js/rounded-corners.js#L64
229+
// Also, when there's not enough space left, we need to back off the smoothing
230+
const maxCornerSmoothing = maxRadius / cornerRadius - 1
231+
cornerSmoothing = Math.min(cornerSmoothing, maxCornerSmoothing)
225232

226-
// 12.2 from the article
227-
const p = Math.min((1 + cornerSmoothing) * cornerRadius, maxRadius)
228-
229-
let angleAlpha: number, angleBeta: number
230-
231-
if (cornerRadius <= maxRadius / 2) {
232-
angleBeta = 90 * (1 - cornerSmoothing)
233-
angleAlpha = 45 * cornerSmoothing
234-
} else {
235-
// When `cornerRadius` is larger and `maxRadius / 2`,
236-
// these angles also depend on `cornerRadius` and `maxRadius / 2`
237-
//
238-
// I did a few tests in Figma and this code generated similar but not identical results
239-
// `diffRatio` was called `change_percentage` in the orignal code
240-
const diffRatio = (cornerRadius - maxRadius / 2) / (maxRadius / 2)
241-
242-
angleBeta = 90 * (1 - cornerSmoothing * (1 - diffRatio))
243-
angleAlpha = 45 * cornerSmoothing * (1 - diffRatio)
244-
}
233+
const p = (1 + cornerSmoothing) * cornerRadius
245234

235+
// These are the angles used in the original code
236+
// angleTheta is not the same as theta in the article
237+
const angleBeta = 90 * (1 - cornerSmoothing)
238+
const angleAlpha = 45 * cornerSmoothing
246239
const angleTheta = (90 - angleBeta) / 2
247240

248241
// This was called `h_longest` in the original code
@@ -253,7 +246,7 @@ function getPathParamsForCorner({
253246
const circularSectionLength =
254247
Math.sin(toRadians(angleBeta / 2)) * cornerRadius * Math.sqrt(2)
255248

256-
// a, b, c and d are from 11.1 in the article
249+
// a, b, c and d are from figure 11.1 in the article
257250
const c = p3ToP4Distance * Math.cos(toRadians(angleAlpha))
258251
const d = c * Math.tan(toRadians(angleAlpha))
259252
const b = (p - circularSectionLength - c - d) / 3

0 commit comments

Comments
 (0)