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 =...