React
by yunyuyuan123
HTML
<div id="root"></div>
React
const { useState, useEffect, useRef } = React;
// Configuration constants
const CARD_CONFIG = {
base: {
width: 400,
height: 400,
color: '#2196F3', // blue-500
},
floatingElements: [
{
style: {
width: 100,
height: 100,
left: 10,
top: 10,
background: '#FF5722',
},
zHeight: 50,
},
{
zHeight: 50,
style: {
width: 100,
height: 100,
right: 10,
bottom: 10,
background: '#FF5722',
},
},
{
zHeight: 100,
style: {
width: 150,
height: 150,
left: '50%',
top: '50%',
transform: 'translate(-50%, -50%)',
background: '#9C27B0',
},
}
],
animation: {
lerpFactor: 0.1,
maxRotation: 20,
perspective: 1000,
}
};
const lerp = (start, end, factor) => {
return start + (end - start) * factor;
};
function PerspectiveCard() {
const wrapperRef = useRef(null);
const sceneRef = useRef(null);
const animationRef = useRef(null);
const targetRotation = useRef({ x: 0, y: 0 });
const currentRotation = useRef({ x: 0, y: 0 });
const animate = () => {
currentRotation.current = {
x: lerp(currentRotation.current.x, targetRotation.current.x, CARD_CONFIG.animation.lerpFactor),
y: lerp(currentRotation.current.y, targetRotation.current.y, CARD_CONFIG.animation.lerpFactor),
};
if (wrapperRef.current) {
if (sceneRef.current) {
sceneRef.current.style.transform = `rotateX(${currentRotation.current.x}deg) rotateY(${currentRotation.current.y}deg)`;
}
}
animationRef.current = requestAnimationFrame(animate);
};
useEffect(() => {
animationRef.current = requestAnimationFrame(animate);
return () => {
if (animationRef.current) {
cancelAnimationFrame(animationRef.current);
}
};
}, []);
const handleMouseMove = (e) => {
if (!wrapperRef.current) return;
const rect =...