Skip to content

Commit

Permalink
Merge pull request #1416 from framer/fix/corrected-borders
Browse files Browse the repository at this point in the history
Crossfade border-radius of "%" and "px" units
  • Loading branch information
mergetron[bot] committed Jan 11, 2022
2 parents 0454553 + 3b802f9 commit bb5f872
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 11 deletions.
100 changes: 100 additions & 0 deletions src/projection/animation/__tests__/mix-values.test.ts
@@ -0,0 +1,100 @@
import { mixValues } from "../mix-values"

describe("mixValues", () => {
test("mixes borderRadius numbers", () => {
const output = {}

mixValues(
output,
{ borderTopLeftRadius: 10 },
{ borderTopLeftRadius: 20 },
0.5,
false,
false
)

expect(output).toEqual({ borderTopLeftRadius: 15 })
})

test("mixes borderRadius px", () => {
const output = {}

mixValues(
output,
{ borderTopLeftRadius: "10px" },
{ borderTopLeftRadius: "20px" },
0.5,
false,
false
)

expect(output).toEqual({ borderTopLeftRadius: 15 })
})

test("mixes borderRadius percentage", () => {
const output = {}

mixValues(
output,
{ borderTopLeftRadius: "10%" },
{ borderTopLeftRadius: "20%" },
0.5,
false,
false
)

expect(output).toEqual({ borderTopLeftRadius: "15%" })
})

test("mixes borderRadius percentage with 0", () => {
const output = {}

mixValues(
output,
{ borderTopLeftRadius: 0 },
{ borderTopLeftRadius: "20%" },
0.5,
false,
false
)

expect(output).toEqual({ borderTopLeftRadius: "10%" })

mixValues(
output,
{ borderTopLeftRadius: "20%" },
{ borderTopLeftRadius: 0 },
0.5,
false,
false
)

expect(output).toEqual({ borderTopLeftRadius: "10%" })
})

test("doesn't mix % with px", () => {
const output = {}

mixValues(
output,
{ borderTopLeftRadius: "10px" },
{ borderTopLeftRadius: "20%" },
0.5,
false,
false
)

expect(output).toEqual({ borderTopLeftRadius: "20%" })

mixValues(
output,
{ borderTopLeftRadius: "20%" },
{ borderTopLeftRadius: "10px" },
0.5,
false,
false
)

expect(output).toEqual({ borderTopLeftRadius: "10px" })
})
})
34 changes: 23 additions & 11 deletions src/projection/animation/mix-values.ts
@@ -1,10 +1,17 @@
import { circOut, linear, mix, progress as calcProgress } from "popmotion"
import { percent, px } from "style-value-types"
import { ResolvedValues } from "../../render/types"
import { EasingFunction } from "../../types"

const borders = ["TopLeft", "TopRight", "BottomLeft", "BottomRight"]
const numBorders = borders.length

const asNumber = (value: string | number) =>
typeof value === "string" ? parseFloat(value) : value

const isPx = (value: string | number) =>
typeof value === "number" || px.test(value)

export function mixValues(
target: ResolvedValues,
follow: ResolvedValues,
Expand Down Expand Up @@ -47,17 +54,22 @@ export function mixValues(
followRadius ||= 0
leadRadius ||= 0

/**
* Currently we're only crossfading between numerical border radius.
* It would be possible to crossfade between percentages for a little
* extra bundle size.
*/
if (
typeof followRadius === "number" &&
typeof leadRadius === "number"
) {
const radius = Math.max(mix(followRadius, leadRadius, progress), 0)
target[borderLabel] = radius
const canMix =
followRadius === 0 ||
leadRadius === 0 ||
isPx(followRadius) === isPx(leadRadius)

if (canMix) {
target[borderLabel] = Math.max(
mix(asNumber(followRadius), asNumber(leadRadius), progress),
0
)

if (percent.test(leadRadius) || percent.test(followRadius)) {
target[borderLabel] += "%"
}
} else {
target[borderLabel] = leadRadius
}
}

Expand Down
1 change: 1 addition & 0 deletions src/projection/styles/scale-border-radius.ts
Expand Up @@ -17,6 +17,7 @@ export function pixelsToPercent(pixels: number, axis: Axis): number {
export const correctBorderRadius: ScaleCorrectorDefinition = {
correct: (latest, node) => {
if (!node.target) return latest

/**
* If latest is a string, if it's a percentage we can return immediately as it's
* going to be stretched appropriately. Otherwise, if it's a pixel, convert it to a number.
Expand Down

0 comments on commit bb5f872

Please sign in to comment.