Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import type { ComponentType } from "react"
- import { useRef, useState } from "react"
- import { useEffect } from "react"
- import { useSpring, animated } from "react-spring"
- export function withCursorFollow(Component): ComponentType {
- return (props) => {
- const ref = useRef(null)
- const [isHovering, setIsHovering] = useState(false)
- const [originalPosition, setOriginalPosition] = useState({
- left: 0,
- top: 0,
- })
- const [centerPosition, setCenterPosition] = useState({
- left: 0,
- top: 0,
- })
- const springProps = useSpring({
- left: isHovering ? originalPosition.left : centerPosition.left,
- top: isHovering ? originalPosition.top : centerPosition.top,
- config: { mass: 1, tension: 170, friction: 26 },
- })
- useEffect(() => {
- if (!ref.current) return
- const buttonRect = ref.current.getBoundingClientRect()
- const elementRect = ref.current.getBoundingClientRect()
- setCenterPosition({
- left: buttonRect.width / 2 - elementRect.width / 2,
- top: buttonRect.height / 2 - elementRect.height / 2,
- })
- const handleMouseMove = (e) => {
- if (!ref.current) return
- if (e.target.closest("button")) {
- setIsHovering(true)
- const buttonRect = e.target.getBoundingClientRect()
- const elementRect = ref.current.getBoundingClientRect()
- setOriginalPosition({
- left:
- buttonRect.left +
- buttonRect.width / 2 -
- (e.clientX + elementRect.width / 2),
- top:
- buttonRect.top +
- buttonRect.height / 2 -
- (e.clientY + elementRect.height / 2),
- })
- setCenterPosition({
- left: buttonRect.width / 2 - elementRect.width / 2,
- top: buttonRect.height / 2 - elementRect.height / 2,
- })
- } else {
- setIsHovering(false)
- }
- }
- window.addEventListener("mousemove", handleMouseMove)
- return () => {
- window.removeEventListener("mousemove", handleMouseMove)
- }
- }, [])
- return (
- <animated.div
- ref={ref}
- style={{
- position: "absolute",
- pointerEvents: "none",
- left: springProps.left,
- top: springProps.top,
- transform: "translate3d(0, 0, 0)",
- transformStyle: "preserve-3d",
- }}
- >
- <Component {...props} />
- </animated.div>
- )
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement