import { type HTMLAttributes, useRef, useState } from 'react';
export const useCardAnimation = () => {
const [pageX, setPageX] = useState(null);
const [pageY, setPageY] = useState(null);
const [isHovering, setIsHovering] = useState(false);
const ref = useRef(null);
const handleMove = ({ pageX, pageY }: { pageX: number; pageY: number }) => {
setPageX(pageX);
setPageY(pageY);
};
const handleTouchMove = (evt: any) => {
evt.preventDefault();
const { pageX, pageY } = evt.touches[0];
handleMove({ pageX, pageY });
};
let shine: string;
let shineBg: string;
let container: string;
let outerContainer: string;
const handleEnter = () => {
setIsHovering(true);
};
const handleLeave = () => {
setIsHovering(false);
};
const ele = ref.current;
if (pageX && pageY && ele && isHovering) {
const rootElemWidth = ele.clientWidth || ele.offsetWidth || ele.scrollWidth;
const rootElemHeight =
ele.clientHeight || ele.offsetHeight || ele.scrollHeight;
const bodyScrollTop =
document.body.scrollTop ||
document.getElementsByTagName('html')[0].scrollTop;
const bodyScrollLeft = document.body.scrollLeft;
const offsets = ele.getBoundingClientRect();
const wMultiple = 320 / rootElemWidth;
const multiple = wMultiple * 0.05;
const offsetX =
0.52 - (pageX - offsets.left - bodyScrollLeft) / rootElemWidth;
const offsetY =
0.52 - (pageY - offsets.top - bodyScrollTop) / rootElemHeight;
const dy = pageY - offsets.top - bodyScrollTop - rootElemHeight / 2;
const dx = pageX - offsets.left - bodyScrollLeft - rootElemWidth / 2;
const yRotate = (offsetX - dx) * multiple;
const xRotate =
(dy - offsetY) * (Math.min(offsets.width / offsets.height, 1) * multiple);
const arad = Math.atan2(dy, dx);
const rawAngle = (arad * 180) / Math.PI - 90;
const angle = rawAngle < 0 ? rawAngle + 360 : rawAngle;
shine = `translateX(${offsetX - 0.1}px) translateY(${offsetY - 0.1}px)`;
shineBg = `linear-gradient(${angle}deg, rgba(255, 255, 255, ${
((pageY - offsets.top - bodyScrollTop) / rootElemHeight) * 0.2
}) 0%, rgba(255, 255, 255, 0) 50%)`;
container = `rotateX(${xRotate}deg) rotateY(${yRotate}deg)`;
outerContainer = `perspective(${rootElemWidth * 2}px)`;
} else {
shine = '';
shineBg = '';
container = '';
outerContainer = '';
}
const outerProps: HTMLAttributes = {
style: {
transform: outerContainer,
transformStyle: 'preserve-3d',
},
onMouseEnter: handleEnter,
onMouseLeave: handleLeave,
onMouseMove: handleMove,
onTouchMove: handleTouchMove,
onTouchStart: handleEnter,
onTouchEnd: handleLeave,
};
const outerRef = ref;
const innerProps = {
style: {
transform: container,
},
};
const shineDom = (
);
return {
outerProps,
outerRef,
innerProps,
shineDom,
};
};