页面转场
ui




















src
TSX
// npm install motion
"use client";
import { useRef } from "react";
import Image from "next/image";
import { motion, useScroll, useSpring, useTransform, useVelocity } from "motion/react";
const strip = [
"https://cdn.pixabay.com/photo/2022/10/24/09/31/flower-7543035_1280.jpg",
"https://cdn.pixabay.com/photo/2020/01/04/20/30/tree-4741598_1280.jpg",
"https://cdn.pixabay.com/photo/2024/12/18/01/27/lightning-9274136_1280.jpg",
"https://cdn.pixabay.com/photo/2025/06/14/17/27/nature-9659850_1280.jpg",
"https://cdn.pixabay.com/photo/2022/12/17/13/46/woods-7661735_1280.jpg",
"https://cdn.pixabay.com/photo/2023/04/16/10/55/nature-7929920_1280.jpg",
"https://cdn.pixabay.com/photo/2025/06/28/17/56/forest-9685700_1280.jpg",
"https://cdn.pixabay.com/photo/2020/03/03/20/31/boat-4899802_1280.jpg",
"https://cdn.pixabay.com/photo/2021/09/13/08/18/blue-flower-6620619_1280.jpg",
"https://cdn.pixabay.com/photo/2023/11/25/12/18/sea-8411640_1280.jpg",
"https://cdn.pixabay.com/photo/2024/01/25/12/30/mountain-8531778_1280.jpg",
"https://cdn.pixabay.com/photo/2025/05/30/17/15/mountain-9631829_1280.jpg",
"https://cdn.pixabay.com/photo/2022/10/11/18/53/autumn-7514966_1280.jpg",
"https://cdn.pixabay.com/photo/2025/05/31/20/23/trees-9634157_1280.jpg",
"https://cdn.pixabay.com/photo/2021/10/07/00/48/boat-6686952_1280.jpg",
"https://cdn.pixabay.com/photo/2025/05/31/21/25/insects-9634230_1280.jpg",
"https://cdn.pixabay.com/photo/2019/12/03/21/29/mountains-4671122_1280.jpg",
"https://cdn.pixabay.com/photo/2019/12/30/05/22/bird-4728857_1280.jpg",
"https://cdn.pixabay.com/photo/2023/09/29/07/52/rocks-8283191_1280.jpg",
"https://cdn.pixabay.com/photo/2019/12/29/04/06/waterfall-4726196_1280.jpg",
];
const HEIGHTS = ["h-56", "h-[24rem]", "h-72", "h-[28rem]", "h-64"];
export default function Page() {
const ref = useRef<HTMLDivElement>(null);
const { scrollYProgress } = useScroll({
target: ref,
offset: ["start start", "end end"],
});
const speed = useSpring(useVelocity(scrollYProgress), {
stiffness: 180,
damping: 40,
mass: 0.4,
});
const x = useTransform(scrollYProgress, [0, 1], ["-88%", "2%"]);
const rotateY = useTransform(speed, [-1.6, 0, 1.6], [24, 0, -24]);
return (
<div ref={ref} className="h-[320vh] bg-white">
<div className="sticky top-0 flex h-screen items-center overflow-hidden [perspective:1800px]">
<motion.div
style={{ x }}
className="flex items-center gap-8 pl-4 [transform-style:preserve-3d]"
>
{strip.map((src, i) => (
<motion.div
key={src}
style={{ rotateY }}
className={"relative w-[27rem] shrink-0 overflow-hidden " + HEIGHTS[i % HEIGHTS.length]}
>
<Image src={src} alt="" fill className="object-cover" />
</motion.div>
))}
</motion.div>
</div>
</div>
);
}