Skip to content

Commit

Permalink
Merge pull request #1829 from framer/fix/map-easing-names
Browse files Browse the repository at this point in the history
Map WAAPI easing names
  • Loading branch information
mergetron[bot] committed Dec 14, 2022
2 parents 6eb920e + 0477e6e commit ca20af9
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 9 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,12 @@ Framer Motion adheres to [Semantic Versioning](http://semver.org/).

Undocumented APIs should be considered internal and may change without warning.

## [7.9.1] 2022-12-14

### Fixed

- Fixing mapping Framer Motion easing names to WAAPI.

## [7.9.0] 2022-12-14

### Added
Expand Down
23 changes: 23 additions & 0 deletions dev/examples/WAAPI-background-color.tsx
@@ -0,0 +1,23 @@
import * as React from "react"
import { useState } from "react"
import { motion } from "framer-motion"

const style = {
width: 100,
height: 100,
background: "white",
}

export const App = () => {
const [state, setState] = useState(false)

return (
<motion.div
initial={{ backgroundColor: "#00f" }}
animate={{ backgroundColor: state ? "#00f" : "#f00" }}
onClick={() => setState(!state)}
transition={{ duration: 1 }}
style={style}
/>
)
}
2 changes: 1 addition & 1 deletion packages/framer-motion/package.json
Expand Up @@ -39,7 +39,7 @@
"clean": "rm -rf types dist lib",
"test": "yarn test-server && yarn test-client",
"test-ci": "yarn test",
"test-client": "jest --config jest.config.json --max-workers=2 src/motion/__tests__/waapi.test.tsx",
"test-client": "jest --config jest.config.json --max-workers=2",
"test-server": "jest --config jest.config.ssr.json ",
"test-watch": "jest --watch --coverage --coverageReporters=lcov --config jest.config.json",
"test-appear": "yarn run collect-appear-tests && start-server-and-test 'pushd ../../; python -m SimpleHTTPServer; popd' http://0.0.0.0:8000 'cypress run -s cypress/integration/appear.chrome.ts --config baseUrl=http://localhost:8000/'",
Expand Down
24 changes: 23 additions & 1 deletion packages/framer-motion/src/animation/waapi/easing.ts
@@ -1,4 +1,26 @@
import { BezierDefinition } from "../../easing/types"
import { BezierDefinition, EasingDefinition } from "../../easing/types"
import { camelToDash } from "../../render/dom/utils/camel-to-dash"

export const cubicBezierAsString = ([a, b, c, d]: BezierDefinition) =>
`cubic-bezier(${a}, ${b}, ${c}, ${d})`

const validWaapiEasing = new Set([
"linear",
"ease-in",
"ease-out",
"ease-in-out",
])

export function mapEasingName(easingName: string): string {
const name = camelToDash(easingName)
return validWaapiEasing.has(name) ? name : "ease"
}

export function mapEasingToNativeEasing(
easing?: EasingDefinition
): string | undefined {
if (!easing) return undefined
return Array.isArray(easing)
? cubicBezierAsString(easing)
: mapEasingName(easing)
}
4 changes: 2 additions & 2 deletions packages/framer-motion/src/animation/waapi/index.ts
@@ -1,4 +1,4 @@
import { cubicBezierAsString } from "./easing"
import { mapEasingToNativeEasing } from "./easing"
import { NativeAnimationOptions } from "./types"

export function animateStyle(
Expand All @@ -19,7 +19,7 @@ export function animateStyle(
{
delay,
duration,
easing: Array.isArray(ease) ? cubicBezierAsString(ease) : ease,
easing: mapEasingToNativeEasing(ease),
fill: "both",
iterations: repeat + 1,
direction: repeatType === "reverse" ? "alternate" : "normal",
Expand Down
120 changes: 120 additions & 0 deletions packages/framer-motion/src/motion/__tests__/waapi.test.tsx
Expand Up @@ -74,6 +74,126 @@ describe("WAAPI animations", () => {
)
})

test("Maps 'easeIn' to 'ease-in'", () => {
const ref = createRef<HTMLDivElement>()
const Component = () => (
<motion.div
ref={ref}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{
ease: "easeIn",
}}
/>
)
const { rerender } = render(<Component />)
rerender(<Component />)

expect(ref.current!.animate).toBeCalled()
expect(ref.current!.animate).toBeCalledWith(
{ opacity: [0, 1], offset: undefined },
{
easing: "ease-in",
delay: -0,
duration: 0.3,
direction: "normal",
fill: "both",
iterations: 1,
}
)
})

test("Maps 'easeOut' to 'ease-out'", () => {
const ref = createRef<HTMLDivElement>()
const Component = () => (
<motion.div
ref={ref}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{
ease: "easeOut",
}}
/>
)
const { rerender } = render(<Component />)
rerender(<Component />)

expect(ref.current!.animate).toBeCalled()
expect(ref.current!.animate).toBeCalledWith(
{ opacity: [0, 1], offset: undefined },
{
easing: "ease-out",
delay: -0,
duration: 0.3,
direction: "normal",
fill: "both",
iterations: 1,
}
)
})

test("Maps 'easeInOut' to 'ease-in-out'", () => {
const ref = createRef<HTMLDivElement>()
const Component = () => (
<motion.div
ref={ref}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{
ease: "easeInOut",
}}
/>
)
const { rerender } = render(<Component />)
rerender(<Component />)

expect(ref.current!.animate).toBeCalled()
expect(ref.current!.animate).toBeCalledWith(
{ opacity: [0, 1], offset: undefined },
{
easing: "ease-in-out",
delay: -0,
duration: 0.3,
direction: "normal",
fill: "both",
iterations: 1,
}
)
})

/**
* TODO: Wait for comments and either bump these back to the main thread,
* generate keyframes, generate linear() easing, or create similar cubic beziers.
*/
test("Maps remaining easings to 'ease'", () => {
const ref = createRef<HTMLDivElement>()
const Component = () => (
<motion.div
ref={ref}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{
ease: "anticipate",
}}
/>
)
const { rerender } = render(<Component />)
rerender(<Component />)

expect(ref.current!.animate).toBeCalled()
expect(ref.current!.animate).toBeCalledWith(
{ opacity: [0, 1], offset: undefined },
{
easing: "ease",
delay: -0,
duration: 0.3,
direction: "normal",
fill: "both",
iterations: 1,
}
)
})

test("WAAPI is called with pre-generated spring keyframes", () => {
const ref = createRef<HTMLDivElement>()
const Component = () => (
Expand Down
10 changes: 5 additions & 5 deletions yarn.lock
Expand Up @@ -7909,8 +7909,8 @@ __metadata:
cache-loader: ^1.2.5
convert-tsconfig-paths-to-webpack-aliases: ^0.9.2
fork-ts-checker-webpack-plugin: ^6.2.0
framer-motion: ^7.8.1
framer-motion-3d: ^7.8.1
framer-motion: ^7.9.0
framer-motion-3d: ^7.9.0
path-browserify: ^1.0.1
react: ^18.2.0
react-dom: ^18.2.0
Expand Down Expand Up @@ -7976,14 +7976,14 @@ __metadata:
languageName: unknown
linkType: soft

"framer-motion-3d@^7.8.1, framer-motion-3d@workspace:packages/framer-motion-3d":
"framer-motion-3d@^7.9.0, framer-motion-3d@workspace:packages/framer-motion-3d":
version: 0.0.0-use.local
resolution: "framer-motion-3d@workspace:packages/framer-motion-3d"
dependencies:
"@react-three/fiber": ^8.2.2
"@react-three/test-renderer": ^9.0.0
"@rollup/plugin-commonjs": ^22.0.1
framer-motion: ^7.8.1
framer-motion: ^7.9.0
react-merge-refs: ^2.0.1
peerDependencies:
"@react-three/fiber": ^8.2.2
Expand All @@ -7993,7 +7993,7 @@ __metadata:
languageName: unknown
linkType: soft

"framer-motion@^7.8.1, framer-motion@workspace:packages/framer-motion":
"framer-motion@^7.9.0, framer-motion@workspace:packages/framer-motion":
version: 0.0.0-use.local
resolution: "framer-motion@workspace:packages/framer-motion"
dependencies:
Expand Down

0 comments on commit ca20af9

Please sign in to comment.