Skip to content

Commit 2947edf

Browse files
committed
Making script backwards compatible
1 parent 827d3e0 commit 2947edf

File tree

5 files changed

+140
-4
lines changed

5 files changed

+140
-4
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<html>
2+
<head>
3+
<style>
4+
body {
5+
padding: 100px;
6+
margin: 0;
7+
}
8+
9+
#box {
10+
width: 100px;
11+
height: 100px;
12+
background-color: #0077ff;
13+
}
14+
15+
[data-layout-correct="false"] {
16+
background: #dd1144 !important;
17+
opacity: 1 !important;
18+
}
19+
</style>
20+
</head>
21+
<body>
22+
<div id="root"></div>
23+
<script src="../../node_modules/react/umd/react.development.js"></script>
24+
<script src="../../node_modules/react-dom/umd/react-dom.development.js"></script>
25+
<script src="../../node_modules/react-dom/umd/react-dom-server-legacy.browser.development.js"></script>
26+
<script src="../../packages/framer-motion/dist/framer-motion.dev.js"></script>
27+
<script src="../projection/script-assert.js"></script>
28+
29+
<script>
30+
const {
31+
motion,
32+
animateStyle,
33+
animate,
34+
startOptimizedAppearAnimation,
35+
optimizedAppearDataAttribute,
36+
motionValue,
37+
frame,
38+
} = window.Motion
39+
const { matchViewportBox } = window.Assert
40+
const root = document.getElementById("root")
41+
42+
const duration = 2
43+
const x = motionValue(0)
44+
45+
let isFirstFrame = true
46+
47+
// This is the tree to be rendered "server" and client-side.
48+
const Component = React.createElement(motion.div, {
49+
id: "box",
50+
initial: { x: 0, opacity: 0 },
51+
animate: { x: 100, opacity: 1 },
52+
transition: { duration, ease: "linear" },
53+
style: { x },
54+
/**
55+
* On animation start, check the values we expect to see here
56+
*/
57+
onAnimationStart: () => {
58+
const box = document.getElementById("box")
59+
60+
box.style.backgroundColor = "green"
61+
62+
setTimeout(() => {
63+
box.style.transform = "scale(2)"
64+
65+
const { width } = box.getBoundingClientRect()
66+
if (width !== 100) {
67+
showError(
68+
document.getElementById("box"),
69+
`Setting transform became visible, which means optimised animation has been prematurely cancelled. Width was ${width}px instead of 200px.`
70+
)
71+
}
72+
}, 100)
73+
},
74+
[optimizedAppearDataAttribute]: "a",
75+
children: "Content",
76+
})
77+
78+
// Emulate server rendering of element
79+
root.innerHTML = ReactDOMServer.renderToString(Component)
80+
81+
// Start optimised opacity animation
82+
startOptimizedAppearAnimation(
83+
document.getElementById("box"),
84+
"opacity",
85+
[0, 1],
86+
{
87+
duration: duration * 1000,
88+
ease: "linear",
89+
}
90+
)
91+
92+
// Start WAAPI animation
93+
const animation = startOptimizedAppearAnimation(
94+
document.getElementById("box"),
95+
"transform",
96+
["translateX(0px)", "translateX(100px)"],
97+
{
98+
duration: duration * 1000,
99+
ease: "linear",
100+
},
101+
(animation) => {
102+
setTimeout(() => {
103+
ReactDOM.hydrateRoot(root, Component)
104+
}, (duration * 1000) / 2)
105+
}
106+
)
107+
</script>
108+
</body>
109+
</html>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
["defer-handoff.html","interrupt-delay-after.html","interrupt-delay-before-accelerated.html","interrupt-delay-before.html","interrupt-spring.html","interrupt-tween-opacity-waapi.html","interrupt-tween-opacity.html","interrupt-tween-transforms.html","interrupt-tween-x.html","persist.html","portal.html","resync-delay.html","resync.html","start-after-hydration.html"]
1+
["defer-handoff.html","interrupt-delay-after.html","interrupt-delay-before-accelerated.html","interrupt-delay-before.html","interrupt-spring.html","interrupt-tween-opacity-waapi.html","interrupt-tween-opacity.html","interrupt-tween-transforms.html","interrupt-tween-x.html","persist-optimised-animation.html","persist.html","portal.html","resync-delay.html","resync.html","start-after-hydration.html"]

packages/framer-motion/src/animation/interfaces/visual-element-target.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { setTarget } from "../../render/utils/setters"
1010
import { AnimationPlaybackControls } from "../types"
1111
import { getValueTransition } from "../utils/transitions"
1212
import { MotionValue } from "../../value"
13+
import { frame } from "../../frameloop"
1314

1415
/**
1516
* Decide whether we should block this animation. Previously, we achieved this
@@ -90,7 +91,12 @@ export function animateTarget(
9091
visualElement.getProps()[optimizedAppearDataAttribute]
9192

9293
if (appearId) {
93-
const elapsed = window.HandoffAppearAnimations(appearId, key)
94+
const elapsed = window.HandoffAppearAnimations(
95+
appearId,
96+
key,
97+
value,
98+
frame
99+
)
94100

95101
if (elapsed !== null) {
96102
valueTransition.elapsed = elapsed

packages/framer-motion/src/animation/optimized-appear/handoff.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { Batcher } from "../../frameloop/types"
2+
import type { MotionValue } from "../../value"
13
import { transformProps } from "../../render/html/utils/transform"
24
import { appearAnimationStore } from "./store"
35
import { appearStoreId } from "./store-id"
@@ -6,7 +8,15 @@ let handoffFrameTime: number
68

79
export function handoffOptimizedAppearAnimation(
810
elementId: string,
9-
valueName: string
11+
valueName: string,
12+
/**
13+
* Legacy arguments. This function is inlined as part of SSG so it can be there's
14+
* a version mismatch between the main included Motion and the inlined script.
15+
*
16+
* Remove in early 2024.
17+
*/
18+
_value: MotionValue,
19+
_frame: Batcher
1020
): number | null {
1121
const optimisedValueName = transformProps.has(valueName)
1222
? "transform"

packages/framer-motion/src/animation/optimized-appear/types.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
1+
import type { Batcher } from "../../frameloop/types"
2+
import type { MotionValue } from "../../value"
3+
14
export type HandoffFunction = (
25
storeId: string,
3-
valueName: string
6+
valueName: string,
7+
/**
8+
* Legacy arguments. This function is inlined as part of SSG so it can be there's
9+
* a version mismatch between the main included Motion and the inlined script.
10+
*
11+
* Remove in early 2024.
12+
*/
13+
_value: MotionValue,
14+
_frame: Batcher
415
) => null | number
516

617
/**

0 commit comments

Comments
 (0)