Created
July 3, 2025 08:05
-
-
Save mattgperry/ad76704eb2e5f2bf0ca942c6dda8f5d4 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
"use client" | |
import { | |
frame, | |
motion, | |
useMotionValue, | |
useSpring, | |
useTransform, | |
useVelocity, | |
} from "motion/react" | |
import { useEffect, useRef } from "react" | |
export default function MotionBlur() { | |
const ref = useRef<HTMLDivElement>(null) | |
const x = useSpring(0, spring) | |
const y = useSpring(0, spring) | |
const xVelocity = useVelocity(x) | |
const yVelocity = useVelocity(y) | |
const width = useMotionValue(100) | |
const height = useMotionValue(100) | |
const xFrameOffset = useTransform(() => Math.abs(xVelocity.get() / 1000)) | |
const yFrameOffset = useTransform(() => Math.abs(yVelocity.get() / 1000)) | |
// const stdDeviation = useTransform( | |
// () => `${xStdDeviation.get()},${yStdDeviation.get()}` | |
// ) | |
const blur = useTransform(() => | |
Math.max(xFrameOffset.get(), yFrameOffset.get()) | |
) | |
const filter = useTransform(() => `blur(${blur.get()}px)`) | |
const transform = useTransform(() => { | |
const w = width.get() | |
const h = height.get() | |
const b = blur.get() | |
const scaleX = w / (w + 2 * b) | |
const scaleY = h / (h + 2 * b) | |
return `translate(${x.get() - xFrameOffset.get()}px, ${ | |
y.get() - yFrameOffset.get() | |
}px) scale(${scaleX}, ${scaleY})` | |
// ;`translate(${x.get() - xStdDeviation.get() / 2}px, ${ | |
// y.get() - yStdDeviation.get() / 2 | |
// }px) scaleY())` | |
}) | |
useEffect(() => { | |
const element = ref.current | |
if (!element) return | |
const moveElement = (event: MouseEvent) => { | |
frame.read(() => { | |
x.set( | |
event.clientX - element.offsetLeft - element.offsetWidth / 2 | |
) | |
y.set( | |
event.clientY - element.offsetTop - element.offsetHeight / 2 | |
) | |
}) | |
} | |
window.addEventListener("pointerdown", moveElement) | |
return () => { | |
window.removeEventListener("pointerdown", moveElement) | |
} | |
}, []) | |
return ( | |
<> | |
<motion.div ref={ref} style={{ ...ball, transform, filter }}> | |
test | |
</motion.div> | |
{/* <svg> | |
<defs> | |
<filter id="blur"> | |
<motion.feGaussianBlur | |
in="SourceGraphic" | |
stdDeviation={stdDeviation} | |
/> | |
</filter> | |
</defs> | |
</svg> */} | |
<style> | |
{` | |
body { overflow: hidden; } | |
`} | |
</style> | |
</> | |
) | |
} | |
const spring = { damping: 3, stiffness: 50, restDelta: 0.001 } | |
/** | |
* ============== Styles ================ | |
*/ | |
const ball = { | |
width: 100, | |
height: 100, | |
backgroundColor: "var(--hue-1)", | |
// borderRadius: "50%", | |
// willChange: "transform, filter", | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment