I want to create a card hover effect in which the card translates according to the mouse position inside the card and the blob follows the mouse position inside the card
the blob
<div
className={`absolute w-[500px] border-none bottom-[50px] h-[1000px] z-[-1] back ${
hovered ? "opacity-95" : "opacity-0"
} `}
style={{
transform: `translateX(${translateX}px) translateY(${
2 * translateY
}px)`,
background: backgroundColor,
borderRadius: "100%",
mixBlendMode: "soft-light",
left: left,
filter: "blur(180px)",
willChange: "transform",
transition: "transform 0.2s cubic-bezier",
}}
></div>
full implementation
import React, { useState, useEffect } from "react";
import { useSpring, animated } from "@react-spring/web";
export type Props = {
children: React.ReactNode;
backgroundColor: string;
direction: string;
left: string;
};
const calc = (x: number, y: number): [number, number, number] => [
-(y - window.innerHeight / 2) / 360,
(x - window.innerWidth / 2) / 240,
1.02,
];
const trans = (x: number, y: number, s: number): string =>
`perspective(900px) rotateX(${-x}deg) rotateY(${-y}deg)`;
const HoverCard: React.FC<Props> = ({
children,
backgroundColor,
direction,
left,
}) => {
const [hovered, setIsHovered] = useState(false);
const [springProps, set] = useSpring(() => ({
xys: [0, 0, 1],
config: { mass: 5, tension: 6000, friction: 1000 },
}));
const [cursorCoords, setCursorCoords] = useState({ x: 0, y: 0 });
useEffect(() => {
const handleMousePosition = (event: MouseEvent) => {
const { clientX: x, clientY: y } = event;
setCursorCoords({ x, y });
};
window.addEventListener("mousemove", handleMousePosition);
return () => {
window.removeEventListener("mousemove", handleMousePosition);
};
}, []);
const calcTranslate = (
coordinate: number,
containerSize: number,
itemSize: number
) => (coordinate / containerSize) * (containerSize - itemSize);
const translateX =
typeof window !== "undefined"
? calcTranslate(cursorCoords.x, window.innerWidth, 600)
: 0;
const translateY =
typeof window !== "undefined"
? calcTranslate(cursorCoords.y, window.innerHeight, 500)
: 0;
const handleMouseMove = (event: React.MouseEvent<HTMLDivElement>) => {
const { clientX: x, clientY: y } = event;
set({ xys: calc(x, y) });
setIsHovered(true);
};
const handleMouseLeave = () => {
set({ xys: [0, 0, 1] });
setIsHovered(false);
};
return (
<animated.div
className=" overflow-hidden mb-3 md:mb-8 rounded-xl"
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
style={{ transform: springProps.xys.to(trans) }}
>
<div
className={`z-[1] relative bg-white dark:bg-[#161b22] h-full border-[#30363d] border-[0.5px] rounded-xl shadow-xl md:flex ${direction} justify-between`}
>
{children}
//this is the blob
<div
className={`absolute w-[500px] border-none bottom-[50px] h-[1000px] z-[-1] back ${
hovered ? "opacity-95" : "opacity-0"
} `}
style={{
transform: `translateX(${translateX}px) translateY(${
2 * translateY
}px)`,
background: backgroundColor,
borderRadius: "100%",
mixBlendMode: "soft-light",
left: left,
filter: "blur(180px)",
willChange: "transform",
transition: "transform 0.2s cubic-bezier",
}}
></div>
</div>
</animated.div>
);
};
export default HoverCard;
In my case the blob is way off the actual mouse position in the card and the card doesn't translate properly
I am expecting to get an effect in which the card will smoothly translate with the mouse position and i can see a blur blob in the background following the cursor inside the card
Any help is much appreciated , Thank you