Skip to content

Commit

Permalink
Merge pull request #1978 from framer/feature/color-waapi
Browse files Browse the repository at this point in the history
Animate `background-color` via WAAPI
  • Loading branch information
mergetron[bot] committed Feb 24, 2023
2 parents 564f353 + f27c271 commit 6614c69
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 29 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ Undocumented APIs should be considered internal and may change without warning.

## [10.0.0] 2023-02-24

### Added

- `background-color` animations are now hardware accelerated.

### Removed

- Removing fallback for `IntersectionObserver`. Use a polyfill for support in older browsers.
Expand All @@ -17,6 +21,10 @@ Undocumented APIs should be considered internal and may change without warning.
- Using `value.onChange` will now throw a warning with instructions to change to `value.on("change", callback)`.
- Using `AnimateSharedLayout` now throws an error.

### Fixed

- `repeat: Infinity` no longer de-opts from pre-generated WAAPI animations.

## [9.1.7] 2023-02-24

### Fixed
Expand Down
6 changes: 3 additions & 3 deletions dev/package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"name": "framer-motion--dev",
"version": "10.0.0",
"version": "10.0.0-alpha.1",
"private": true,
"scripts": {
"dev": "webpack serve --config ./webpack/config.js --hot"
},
"dependencies": {
"@react-three/drei": "^7.27.3",
"@react-three/fiber": "^8.2.2",
"framer-motion": "^10.0.0",
"framer-motion-3d": "^10.0.0",
"framer-motion": "^10.0.0-alpha.1",
"framer-motion-3d": "^10.0.0-alpha.1",
"path-browserify": "^1.0.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "10.0.0",
"version": "10.0.0-alpha.1",
"packages": [
"packages/*"
],
Expand Down
4 changes: 2 additions & 2 deletions packages/framer-motion-3d/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "framer-motion-3d",
"version": "10.0.0",
"version": "10.0.0-alpha.1",
"description": "A simple and powerful React animation library for @react-three/fiber",
"main": "dist/cjs/index.js",
"module": "dist/es/index.mjs",
Expand Down Expand Up @@ -46,7 +46,7 @@
"postpublish": "git push --tags"
},
"dependencies": {
"framer-motion": "^10.0.0",
"framer-motion": "^10.0.0-alpha.1",
"react-merge-refs": "^2.0.1"
},
"peerDependencies": {
Expand Down
12 changes: 6 additions & 6 deletions packages/framer-motion/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "framer-motion",
"version": "10.0.0",
"version": "10.0.0-alpha.1",
"description": "A simple and powerful React animation library",
"main": "dist/cjs/index.js",
"module": "dist/es/index.mjs",
Expand Down Expand Up @@ -70,31 +70,31 @@
"bundlesize": [
{
"path": "./dist/size-rollup-motion.js",
"maxSize": "29.92 kB"
"maxSize": "29.88 kB"
},
{
"path": "./dist/size-rollup-m.js",
"maxSize": "4.69 kB"
},
{
"path": "./dist/size-rollup-dom-animation.js",
"maxSize": "14.85 kB"
"maxSize": "14.75 kB"
},
{
"path": "./dist/size-rollup-dom-max.js",
"maxSize": "25.67 kB"
"maxSize": "25.61 kB"
},
{
"path": "./dist/size-webpack-m.js",
"maxSize": "4.8 kB"
},
{
"path": "./dist/size-webpack-dom-animation.js",
"maxSize": "18.81 kB"
"maxSize": "18.75 kB"
},
{
"path": "./dist/size-webpack-dom-max.js",
"maxSize": "30.52 kB"
"maxSize": "30.47 kB"
}
],
"gitHead": "79675ba44230ae86bfb212be8bd903fc68524976"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const acceleratedValues = new Set<string>([
"clipPath",
"filter",
"transform",
"backgroundColor",
])

/**
Expand All @@ -26,6 +27,14 @@ const acceleratedValues = new Set<string>([
*/
const sampleDelta = 10 //ms

const requiresPregeneratedKeyframes = (
valueName: string,
options: AnimationOptions
) =>
options.type === "spring" ||
valueName === "backgroundColor" ||
!isWaapiSupportedEasing(options.ease)

export function createAcceleratedAnimation(
value: MotionValue,
valueName: string,
Expand All @@ -45,14 +54,12 @@ export function createAcceleratedAnimation(
/**
* If this animation needs pre-generated keyframes then generate.
*/
if (options.type === "spring" || !isWaapiSupportedEasing(options.ease)) {
/**
* If we need to pre-generate keyframes and repeat is infinite then
* early return as this will lock the thread.
*/
if (options.repeat === Infinity) return

const sampleAnimation = animateValue({ ...options, elapsed: 0 })
if (requiresPregeneratedKeyframes(valueName, options)) {
const sampleAnimation = animateValue({
...options,
repeat: 0,
elapsed: 0,
})
let state = { done: false, value: keyframes[0] }
const pregeneratedKeyframes: number[] = []

Expand Down
127 changes: 123 additions & 4 deletions packages/framer-motion/src/motion/__tests__/waapi.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,67 @@ describe("WAAPI animations", () => {
)
})

test("backgroundColor animates with WAAPI at default settings", () => {
const ref = createRef<HTMLDivElement>()
const Component = () => (
<motion.div
ref={ref}
initial={{ backgroundColor: "#f00" }}
animate={{ backgroundColor: "#00f" }}
/>
)
const { rerender } = render(<Component />)
rerender(<Component />)

expect(ref.current!.animate).toBeCalled()
expect(ref.current!.animate).toBeCalledWith(
{
backgroundColor: [
"rgba(255, 0, 0, 1)",
"rgba(253, 0, 35, 1)",
"rgba(249, 0, 56, 1)",
"rgba(244, 0, 75, 1)",
"rgba(237, 0, 94, 1)",
"rgba(229, 0, 112, 1)",
"rgba(220, 0, 128, 1)",
"rgba(211, 0, 144, 1)",
"rgba(200, 0, 158, 1)",
"rgba(190, 0, 171, 1)",
"rgba(179, 0, 182, 1)",
"rgba(168, 0, 192, 1)",
"rgba(157, 0, 201, 1)",
"rgba(147, 0, 209, 1)",
"rgba(136, 0, 215, 1)",
"rgba(126, 0, 222, 1)",
"rgba(116, 0, 227, 1)",
"rgba(107, 0, 232, 1)",
"rgba(97, 0, 236, 1)",
"rgba(88, 0, 239, 1)",
"rgba(79, 0, 242, 1)",
"rgba(71, 0, 245, 1)",
"rgba(62, 0, 247, 1)",
"rgba(54, 0, 249, 1)",
"rgba(46, 0, 251, 1)",
"rgba(38, 0, 252, 1)",
"rgba(30, 0, 253, 1)",
"rgba(22, 0, 254, 1)",
"rgba(15, 0, 255, 1)",
"rgba(7, 0, 255, 1)",
"rgba(0, 0, 255, 1)",
],
offset: undefined,
},
{
delay: -0,
duration: 300,
easing: "linear",
iterations: 1,
direction: "normal",
fill: "both",
}
)
})

test("opacity animates with WAAPI when no value is originally provided via initial", () => {
const ref = createRef<HTMLDivElement>()
const Component = () => (
Expand Down Expand Up @@ -750,19 +811,77 @@ describe("WAAPI animations", () => {
expect(ref.current!.animate).not.toBeCalled()
})

test("Doesn't animate with WAAPI if repeat is Infinity and we need to generate keyframes", () => {
test("Animates with WAAPI if repeat is defined and we need to generate keyframes", () => {
const ref = createRef<HTMLDivElement>()
const Component = () => (
<motion.div
ref={ref}
initial={{ opacity: 0 }}
animate={{ opacity: 0.8 }}
transition={{ repeat: Infinity, type: "spring" }}
animate={{ opacity: 0.9 }}
transition={{
ease: "backInOut",
duration: 0.05,
repeat: 2,
}}
/>
)
const { rerender } = render(<Component />)
rerender(<Component />)

expect(ref.current!.animate).not.toBeCalled()
expect(ref.current!.animate).toBeCalled()
expect(ref.current!.animate).toBeCalledWith(
{
opacity: [
0, -0.038019759996313955, 0.14036703066311026,
0.7596329693368897, 0.9380197599963139, 0.9,
],
offset: undefined,
},
{
delay: -0,
direction: "normal",
duration: 50,
easing: "linear",
fill: "both",
iterations: 3,
}
)
})

test("Animates with WAAPI if repeat is Infinity and we need to generate keyframes", () => {
const ref = createRef<HTMLDivElement>()
const Component = () => (
<motion.div
ref={ref}
initial={{ opacity: 0 }}
animate={{ opacity: 0.9 }}
transition={{
ease: "backInOut",
duration: 0.05,
repeat: Infinity,
}}
/>
)
const { rerender } = render(<Component />)
rerender(<Component />)

expect(ref.current!.animate).toBeCalled()
expect(ref.current!.animate).toBeCalledWith(
{
opacity: [
0, -0.038019759996313955, 0.14036703066311026,
0.7596329693368897, 0.9380197599963139, 0.9,
],
offset: undefined,
},
{
delay: -0,
direction: "normal",
duration: 50,
easing: "linear",
fill: "both",
iterations: Infinity,
}
)
})
})
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7844,8 +7844,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: ^10.0.0
framer-motion-3d: ^10.0.0
framer-motion: ^10.0.0-alpha.1
framer-motion-3d: ^10.0.0-alpha.1
path-browserify: ^1.0.1
react: ^18.2.0
react-dom: ^18.2.0
Expand Down Expand Up @@ -7911,14 +7911,14 @@ __metadata:
languageName: unknown
linkType: soft

"framer-motion-3d@^10.0.0, framer-motion-3d@workspace:packages/framer-motion-3d":
"framer-motion-3d@^10.0.0-alpha.1, 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: ^10.0.0
framer-motion: ^10.0.0-alpha.1
react-merge-refs: ^2.0.1
peerDependencies:
"@react-three/fiber": ^8.2.2
Expand All @@ -7928,7 +7928,7 @@ __metadata:
languageName: unknown
linkType: soft

"framer-motion@^10.0.0, framer-motion@workspace:packages/framer-motion":
"framer-motion@^10.0.0-alpha.1, 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 6614c69

Please sign in to comment.