import React, { useEffect, useRef } from 'react'; import styled from 'styled-components'; // 导入图片资源 import mono from '@/assets/3dr_mono.png'; import chihiro from '@/assets/3dr_chihiro.png'; import howlcastle from '@/assets/3dr_howlcastle.png'; import monobg from '@/assets/3dr_monobg.jpg'; import spirited from '@/assets/3dr_spirited.jpg'; import howlbg from '@/assets/3dr_howlbg.jpg'; const Parallax = () => { const pageXRef = useRef(null); const cardsRef = useRef(null); useEffect(() => { const pageX = pageXRef.current; const cards = cardsRef.current; const images = document.querySelectorAll('.card__img'); const backgrounds = document.querySelectorAll('.card__bg'); let timeout; const range = 40; // 计算旋转角度 const calcValue = (a, b) => ((a / b) * range - range / 2).toFixed(1); // 视差动画函数 const parallax = (e) => { const x = e.clientX; const y = e.clientY; if (timeout) { window.cancelAnimationFrame(timeout); } timeout = window.requestAnimationFrame(() => { const xValue = calcValue(x, window.innerWidth); const yValue = calcValue(y, window.innerHeight); // 设置卡片容器的旋转角度 cards.style.transform = `rotateX(${yValue}deg) rotateY(${xValue}deg)`; // 设置所有图片的位移 images.forEach(item => { item.style.transform = `translateX(${-xValue}px) translateY(${yValue}px)`; }); // 设置所有背景的位置 backgrounds.forEach(item => { item.style.backgroundPosition = `${xValue * 0.45}px ${-yValue * 0.45}px`; }); }); }; pageX.addEventListener('mousemove', parallax, false); return () => { if (pageX) { pageX.removeEventListener('mousemove', parallax); } }; }, []); return (

Movies

Popular

{/* 幽灵公主 */} Princess Mononoke {/* 千与千寻 */} Spirited Away {/* 哈尔的移动城堡 */} Howl's Moving Castle
); }; // 样式定义 const PageX = styled.div` width: 1000px; height: 700px; display: flex; justify-content: center; align-items: center; overflow: hidden; perspective: 1800px; background: #642b73; background: linear-gradient(to bottom, #c6426e, #642b73); `; const Cards = styled.div` display: inline-block; min-width: 595px; padding: 30px 35px; perspective: 1800px; transform-origin: 50% 50%; transform-style: preserve-3d; border-radius: 15px; text-align: left; background: #fff; box-shadow: 0px 10px 20px 20px rgba(0, 0, 0, 0.17); h1 { margin-bottom: 30px; transform: translateZ(35px); letter-spacing: -1px; font-size: 32px; font-weight: 800; color: #3e3e42; } h3 { margin-bottom: 6px; transform: translateZ(25px); font-size: 16px; color: #eb285d; } `; const Card = styled.div` display: inline-block; width: 175px; height: 250px; position: relative; overflow: hidden; perspective: 1200px; transform-style: preserve-3d; transform: translatez(35px); transition: transform 200ms ease-out; text-align: center; border-radius: 15px; box-shadow: 5px 5px 20px -5px rgba(0, 0, 0, 0.6); &:not(:last-child) { margin-right: 30px; } &.princess-mononoke .card__img { top: 14px; right: -10px; height: 110%; } &.spirited-away .card__img { top: 25px; } &.howl-s-moving-castle .card__img { top: 5px; left: -4px; height: 110%; } `; const CardBg = styled.div` bottom: -50px; left: -50px; position: absolute; right: -50px; top: -50px; transform-origin: 50% 50%; transform: translateZ(-50px); z-index: 0; background: ${props => `url(${props.bg}) center/cover no-repeat`}; `; const CardImg = styled.img` position: relative; height: 100%; `; const CardText = styled.div` display: flex; flex-direction: column; justify-content: center; align-items: center; width: 100%; height: 70px; position: absolute; z-index: 2; bottom: 0; background: linear-gradient( to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.55) 100% ); `; const CardTitle = styled.p` margin-bottom: 3px; padding: 0 10px; font-size: 18px; font-weight: 700; color: #fff; `; export default Parallax;