Skip to content

Instantly share code, notes, and snippets.

@geroembser
Created July 24, 2022 22:46
Show Gist options
  • Save geroembser/9c860ceae1f9fb78ada6f0b0558a35d0 to your computer and use it in GitHub Desktop.
Save geroembser/9c860ceae1f9fb78ada6f0b0558a35d0 to your computer and use it in GitHub Desktop.
Framer Sites Scroll Animations
import type { ComponentType } from "react"
import type { MotionValue, Transition } from "framer-motion"
import {
useViewportScroll,
useVelocity,
useTransform,
useAnimation,
useMotionValue,
animate,
} from "framer-motion"
////////////////////////
// HELPER FUNCTIONS
////////////////////////
function limitValue(value: number, min: number, max: number): number {
if (value > max) {
return max
}
if (value < min) {
return min
}
return value
}
export function getPercentDestinationMover(
Component: any,
speed: number,
destinationOffset: { x: number; y: number },
maxScrollPercent: number = 1.0, //set this to e.g. 0.5 to interpret 50% scrolling OF THE VIEWPORT (i.e. of the visible window!) as 100%
limitToViewportBounds: boolean = false
): ComponentType {
return (props) => {
const { scrollY, scrollYProgress } = useViewportScroll()
const limit_fnct = !limitToViewportBounds
? (v) => v
: (v) => limitValue(v, -1, 0) //from -1 to 0, because we're scrolling down...
const x = useTransform(
scrollYProgress,
(scrollProgress) =>
-speed *
limit_fnct(scrollProgress / maxScrollPercent) *
destinationOffset.x
)
const y = useTransform(
scrollYProgress,
(scrollProgress) =>
-speed *
limit_fnct(scrollProgress / maxScrollPercent) *
destinationOffset.y
)
return <Component {...props} style={{ x: x, y: y }} />
}
}
export function getPercentOpacityChanger(
Component: any,
speed: number,
destinationOpacity: number,
startAtViewportPercentage: number = 0.0 //only start animating if viewport has already scrolled more than that amount of percent
): ComponentType {
return (props) => {
const { scrollY, scrollYProgress } = useViewportScroll()
const opacity = useTransform(
scrollYProgress,
(scrollProgress) =>
(1 / speed) *
((1 -
limitValue(
-scrollProgress - startAtViewportPercentage,
0,
1
) /
(1 - startAtViewportPercentage)) *
(1 - destinationOpacity))
)
return <Component {...props} style={{ opacity: opacity }} />
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment