Created
July 24, 2022 22:46
-
-
Save geroembser/9c860ceae1f9fb78ada6f0b0558a35d0 to your computer and use it in GitHub Desktop.
Framer Sites Scroll Animations
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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