Skip to content

Commit

Permalink
Merge pull request #2421 from framer/fix/skip-mount-animations
Browse files Browse the repository at this point in the history
Skip needless animations
  • Loading branch information
mergetron[bot] committed Nov 30, 2023
2 parents 8cc5349 + 9e289b1 commit c0ebab1
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 1 deletion.
1 change: 1 addition & 0 deletions dev/examples/Animation-animate.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from "react"
import { useEffect, useState } from "react"
import { motion, motionValue, useAnimate } from "framer-motion"
import { frame } from "framer-motion"

/**
* An example of the tween transition type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { animateMotionValue } from "./motion-value"
import { isWillChangeMotionValue } from "../../value/use-will-change/is"
import { setTarget } from "../../render/utils/setters"
import { AnimationPlaybackControls, Transition } from "../types"
import { getValueTransition } from "../utils/transitions"

/**
* Decide whether we should block this animation. Previously, we achieved this
Expand Down Expand Up @@ -65,18 +66,20 @@ export function animateTarget(
const valueTransition = {
delay,
elapsed: 0,
...transition,
...getValueTransition(transition || {}, key),
}

/**
* If this is the first time a value is being animated, check
* to see if we're handling off from an existing animation.
*/
let canSkipHandoff = true
if (window.HandoffAppearAnimations && !value.hasAnimated) {
const appearId =
visualElement.getProps()[optimizedAppearDataAttribute]

if (appearId) {
canSkipHandoff = false
valueTransition.elapsed = window.HandoffAppearAnimations(
appearId,
key,
Expand All @@ -87,6 +90,30 @@ export function animateTarget(
}
}

let canSkip = canSkipHandoff && valueTarget === value.get()

if (
valueTransition.type === "spring" &&
(value.getVelocity() || valueTransition.velocity)
) {
canSkip = false
}

if (canSkip) continue

/**
* Skip this animation if the value hasn't changed. With an exception
* that we can't skip if it's a spring animation
*/
if (
canSkipHandoff &&
valueTarget === value.get() &&
(valueTransition.type !== "spring" ||
(!value.getVelocity() && !valueTransition.velocity))
) {
continue
}

value.start(
animateMotionValue(
key,
Expand Down
57 changes: 57 additions & 0 deletions packages/framer-motion/src/motion/__tests__/animate-prop.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,63 @@ describe("animate prop as object", () => {
})
return expect(promise).resolves.toHaveStyle("font-weight: 100")
})
test("doesn't animate no-op values", async () => {
const promise = new Promise((resolve) => {
let isAnimating = false
const Component = () => (
<motion.div
initial={{ opacity: 1, x: 0 }}
animate={{ opacity: 1, x: 0 }}
transition={{
opacity: { duration: 2, type: "tween", velocity: 100 },
x: { type: "spring", velocity: 0 },
}}
onAnimationStart={() => {
isAnimating = true
}}
onAnimationComplete={() => {
isAnimating = false
}}
/>
)
const { rerender } = render(<Component />)
rerender(<Component />)

frame.postRender(() => {
frame.postRender(() => resolve(isAnimating))
})
})

return expect(promise).resolves.toBe(false)
})
test("does animate no-op values if velocity is non-zero and animation type is spring", async () => {
const promise = new Promise<boolean>((resolve) => {
let isAnimating = false
const Component = () => (
<motion.div
initial={{ opacity: 1 }}
animate={{
opacity: 1,
transition: { type: "spring", velocity: 100 },
}}
onAnimationStart={() => {
isAnimating = true
}}
onAnimationComplete={() => {
isAnimating = false
}}
/>
)
const { rerender } = render(<Component />)
rerender(<Component />)

frame.postRender(() => {
frame.postRender(() => resolve(isAnimating))
})
})

return expect(promise).resolves.toBe(true)
})
test("doesn't animate zIndex", async () => {
const promise = new Promise((resolve) => {
const Component = () => <motion.div animate={{ zIndex: 100 }} />
Expand Down

0 comments on commit c0ebab1

Please sign in to comment.