diff --git a/dev/optimized-appear/defer-handoff-layout.html b/dev/optimized-appear/defer-handoff-layout.html new file mode 100644 index 0000000000..6228597fc8 --- /dev/null +++ b/dev/optimized-appear/defer-handoff-layout.html @@ -0,0 +1,131 @@ + + + + + +
+ + + + + + + + + diff --git a/packages/framer-motion/src/animation/optimized-appear/handoff.ts b/packages/framer-motion/src/animation/optimized-appear/handoff.ts index ad6315237e..183ce8bca2 100644 --- a/packages/framer-motion/src/animation/optimized-appear/handoff.ts +++ b/packages/framer-motion/src/animation/optimized-appear/handoff.ts @@ -32,6 +32,7 @@ export function handoffOptimizedAppearAnimation( const cancelAnimation = () => { appearAnimationStore.delete(storeId) + try { animation.cancel() } catch (error) {} diff --git a/packages/framer-motion/src/animation/optimized-appear/start.ts b/packages/framer-motion/src/animation/optimized-appear/start.ts index daf8109c3b..79a334400f 100644 --- a/packages/framer-motion/src/animation/optimized-appear/start.ts +++ b/packages/framer-motion/src/animation/optimized-appear/start.ts @@ -58,6 +58,16 @@ export function startOptimizedAppearAnimation( animation: readyAnimation, startTime: null, }) + + if (!window.HandoffCancelAllAnimations) { + window.HandoffCancelAllAnimations = () => { + appearAnimationStore.forEach(({ animation }) => { + animation.cancel() + }) + appearAnimationStore.clear() + window.HandoffCancelAllAnimations = undefined + } + } } const startAnimation = () => { diff --git a/packages/framer-motion/src/animation/optimized-appear/types.ts b/packages/framer-motion/src/animation/optimized-appear/types.ts index 4d8e5d45f7..17c07b791a 100644 --- a/packages/framer-motion/src/animation/optimized-appear/types.ts +++ b/packages/framer-motion/src/animation/optimized-appear/types.ts @@ -22,5 +22,6 @@ declare global { interface Window { HandoffAppearAnimations?: HandoffFunction HandoffComplete?: boolean + HandoffCancelAllAnimations?: VoidFunction } } diff --git a/packages/framer-motion/src/projection/node/create-projection-node.ts b/packages/framer-motion/src/projection/node/create-projection-node.ts index a0ee244ce6..c9333efc42 100644 --- a/packages/framer-motion/src/projection/node/create-projection-node.ts +++ b/packages/framer-motion/src/projection/node/create-projection-node.ts @@ -57,6 +57,7 @@ import { steps } from "../../frameloop/frame" import { noop } from "../../utils/noop" import { time } from "../../frameloop/sync-time" import { microtask } from "../../frameloop/microtask" +import { optimizedAppearDataAttribute } from "../../animation/optimized-appear/data-id" const transformAxes = ["", "X", "Y", "Z"] @@ -628,6 +629,9 @@ export function createProjectionNode({ /** * Write */ + if (window.HandoffCancelAllAnimations) { + window.HandoffCancelAllAnimations() + } this.nodes!.forEach(resetTransformStyle) /** @@ -1486,6 +1490,7 @@ export function createProjectionNode({ cancelFrame(this.pendingAnimation) this.pendingAnimation = undefined } + /** * Start the animation in the next frame to have a frame with progress 0, * where the target is the same as when the animation started, so we can