Last active
March 14, 2026 04:39
-
-
Save pabliqe/f803cbeedb949e5673c00592e06212a9 to your computer and use it in GitHub Desktop.
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 { useRef, useState, useEffect } from "react" | |
| import { | |
| motion, | |
| useScroll, | |
| useVelocity, | |
| useTransform, | |
| useSpring, | |
| } from "framer-motion" | |
| // --- CONFIGURATION --- | |
| const CONFIG = { | |
| randomIntensity: 0.5, // Higher = more chance | Range 0–1 | |
| intensity: 1.5, // Higher = more movement (multiplier) | |
| maxRotation: 15, // Max degrees it can tilt | |
| maxTranslate: 100, // Max pixels it can shift X/Y | |
| // Inertia Settings (The "Physics") | |
| stiffness: 300, // Higher = Snappier/Faster reaction | Range: 1–1000 (400) | |
| damping: 50, // Higher = Stops sooner (less "jiggle") | Range: 0–100 (30) | |
| mass: 1, // Higher = Feels "heavier" | Range: 0.1—10 (1) | |
| } | |
| function randomize() { | |
| return Math.floor(Math.random() * (1 - 0 + 1)) | |
| } | |
| export function withRotation(Component): ComponentType { | |
| return (props) => { | |
| // Generate a stable random seed for this instance (-0.5 to 0.5) | |
| const [randomSeed] = useState(() => Math.random() - 0.5) | |
| const { scrollY } = useScroll() | |
| const scrollVelocity = useVelocity(scrollY) | |
| // The "Spring" creates the inertia/wind feel | |
| const smoothVelocity = useSpring(scrollVelocity, { | |
| mass: CONFIG.mass, | |
| stiffness: CONFIG.stiffness, | |
| damping: CONFIG.damping, | |
| }) | |
| // Velocity range: -3000 (fast up) to 3000 (fast down) | |
| const velocityRange = [-3000, 3000] | |
| // Calculate the "Impact" | |
| // If randomIntensity is 0.5, this results in a multiplier between 0.75 and 1.25 | |
| const calcIntensity = | |
| CONFIG.intensity * (1 + randomSeed * CONFIG.randomIntensity) | |
| // Map velocity to movement based on CONFIG | |
| const rotate = useTransform(smoothVelocity, velocityRange, [ | |
| CONFIG.maxRotation * calcIntensity, | |
| -CONFIG.maxRotation * calcIntensity, | |
| ]) | |
| return ( | |
| <Component | |
| {...props} | |
| style={{ | |
| ...props.style, | |
| rotate, | |
| }} | |
| /> | |
| ) | |
| } | |
| } | |
| export function withInertia(Component): ComponentType { | |
| return (props) => { | |
| // Generate a stable random seed for this instance (-0.5 to 0.5) | |
| const [randomSeed] = useState(() => Math.random() - 0.5) | |
| const { scrollY } = useScroll() | |
| const scrollVelocity = useVelocity(scrollY) | |
| // The "Spring" creates the inertia/wind feel | |
| const smoothVelocity = useSpring(scrollVelocity, { | |
| mass: CONFIG.mass, | |
| stiffness: CONFIG.stiffness, | |
| damping: CONFIG.damping, | |
| }) | |
| // Velocity range: -3000 (fast up) to 3000 (fast down) | |
| const velocityRange = [-3000, 3000] | |
| // Map velocity to movement based on CONFIG | |
| // const rotate = useTransform(smoothVelocity, velocityRange, [ | |
| // CONFIG.maxRotation * 0.5, | |
| // -(CONFIG.maxRotation * 0.5), | |
| // ]) | |
| // const translateX = useTransform(smoothVelocity, velocityRange, [ | |
| // -CONFIG.maxTranslate * CONFIG.intensity, | |
| // CONFIG.maxTranslate * CONFIG.intensity, | |
| // ]) | |
| // Calculate the "Impact" | |
| // If randomIntensity is 0.5, this results in a multiplier between 0.75 and 1.25 | |
| const calcIntensity = | |
| CONFIG.intensity * (1 + randomSeed * CONFIG.randomIntensity) | |
| const translateY = useTransform(smoothVelocity, velocityRange, [ | |
| CONFIG.maxTranslate * calcIntensity, | |
| -CONFIG.maxTranslate * calcIntensity, | |
| ]) | |
| return ( | |
| <Component | |
| {...props} | |
| style={{ | |
| ...props.style, | |
| // rotate, | |
| // X: translateX, | |
| y: translateY, | |
| // Optional: add a slight Y lift when scrolling fast | |
| // y: useTransform( | |
| // smoothVelocity, | |
| // [-3000, 0, 3000], | |
| // [-10, 0, -10] | |
| // ), | |
| }} | |
| /> | |
| ) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment