组件
视差滚动 Parallax
依据页面或局部容器滚动进度,以差异化速率与缩放变换驱动图层位移的深度空间视觉组件。
基础用法
在局部滚动容器中向下滚动:背景图、标题与下方三张图片以不同速度和方向移动,形成纵深层次:
Loading…
安装与引入
通过 CLI 自动添加组件,或手动复制源码至项目中:
pnpm dlx @wui-design/cli@latest add @wui/parallax安装基础依赖与动效库
pnpm add motion lucide-react class-variance-authority clsx tailwind-merge复制组件源码到
components/ui/parallax.tsx"use client"
import * as React from "react"
import {
motion,
useReducedMotion,
useScroll,
useSpring,
useTransform,
type HTMLMotionProps,
type SpringOptions,
type UseScrollOptions,
} from "motion/react"
import { cn } from "@/lib/utils"
export interface ParallaxProps extends Omit<
HTMLMotionProps<"div">,
"children"
> {
/** Content translated as the wrapper crosses the viewport. */
children: React.ReactNode
/** Translation axis. @default "y" */
axis?: "x" | "y"
/** Translation range in pixels from scroll start to end. @default [-48, 48] */
distance?: [number, number]
/** Optional scale range, useful for image-within-frame parallax. */
scale?: [number, number]
/** Optional rotation range in degrees. */
rotate?: [number, number]
/** Optional opacity range. */
opacity?: [number, number]
/** Follow scroll through a spring for a softer, trailing layer. Pass spring options to tune it. @default false */
smooth?: boolean | SpringOptions
/** Scrollable element to observe instead of the page. */
container?: React.RefObject<HTMLElement | null>
/** Motion scroll offsets for the wrapper. @default ["start end", "end start"] */
offset?: UseScrollOptions["offset"]
}
const defaultSpring: SpringOptions = {
stiffness: 120,
damping: 24,
mass: 0.4,
restDelta: 0.0005,
}
/** Moves a layer at a different rate while it crosses the viewport. */
function Parallax({
children,
axis = "y",
distance = [-48, 48],
scale,
rotate,
opacity,
smooth = false,
container,
offset = ["start end", "end start"],
className,
style,
...props
}: ParallaxProps) {
const target = React.useRef<HTMLDivElement>(null)
const reduceMotion = useReducedMotion()
const { scrollYProgress } = useScroll({ target, container, offset })
const springProgress = useSpring(
scrollYProgress,
typeof smooth === "object" ? smooth : defaultSpring
)
const progress = smooth ? springProgress : scrollYProgress
const translation = useTransform(progress, [0, 1], distance)
const scaleValue = useTransform(progress, [0, 1], scale ?? [1, 1])
const rotateValue = useTransform(progress, [0, 1], rotate ?? [0, 0])
const opacityValue = useTransform(progress, [0, 1], opacity ?? [1, 1])
return (
<motion.div
ref={target}
data-slot="parallax"
data-axis={axis}
className={cn("will-change-transform", className)}
style={{
...style,
x: reduceMotion || axis === "y" ? 0 : translation,
y: reduceMotion || axis === "x" ? 0 : translation,
scale: reduceMotion ? 1 : scaleValue,
rotate: reduceMotion ? 0 : rotateValue,
opacity: reduceMotion || !opacity ? style?.opacity : opacityValue,
}}
{...props}
>
{children}
</motion.div>
)
}
export { Parallax }
属性 Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| children | React.ReactNode | — | 受视差滚动力度驱动变换的子图层元素(如图片、文字标语、浮动卡片)。 |
| axis | "x" | "y" | "y" | 视差变换的位移主轴。 |
| distance | [number, number] | [-48, 48] | 从视差起始点到结束点的位移区间(单位:像素)。例如 [-100, 100] 表示由上至下位移 200px。 |
| scale | [number, number] | — | 伴随滚动进度同步插值的缩放比例区间,如 [1.0, 1.25] 可实现深邃的画框缩放视差。 |
| rotate | [number, number] | — | 伴随滚动进度插值的旋转角度区间(度)。 |
| opacity | [number, number] | — | 伴随滚动进度插值的不透明度区间,常用于文字随进入视口淡入。 |
| smooth | boolean | SpringOptions | false | 让图层通过弹簧跟随滚动进度,产生轻微的惯性拖尾。可传入弹簧参数自定义手感。 |
| container | React.RefObject<HTMLElement | null> | — | 局部滚动容器的 ref 引用。不传时默认监听整个全局 window 视口滚动。 |
| offset | UseScrollOptions["offset"] | ["start end", "end start"] | Motion useScroll 监听的视口交叉触发锚点区间。 |
| className | string | — | 应用于视差动画外层的 CSS 类名(通常配合 will-change-transform 优化渲染)。 |
使用场景与设计规范
Parallax 适用于官网 Hero 首屏、沉浸式品牌故事页、媒体图文画廊:
- 分层速率递进:背景层使用低速慢移(如
distance={[-30, 30]}),中景使用标准速度,前景点缀元素使用大位移(如distance={[-100, 100]}),能够营造出极强的真实 3D 纵深感。 - 画框内裁切:对图片外层使用
overflow-hidden,并让缩放余量大于位移量(或把图层向外扩展,如-inset-y-20),避免图片在位移边缘露白。 - 惯性拖尾:前景小元素开启
smooth会显得更轻盈;大面积背景保持默认的直接绑定,避免与滚动产生错位感。
场景示例
画框内缩放
图片在固定画框内同时缩放与位移,说明文字通过 opacity 与自定义 offset 随后淡入:
Loading…
无障碍与交互 Accessibility
- 自动静止降级:当系统配置了
prefers-reduced-motion: reduce时,组件将直接将x、y位移重置为 0,scale重置为 1,完全消除晃动感。 - 硬件加速:自动附带
will-change-transform类名,交由 GPU 独立合成图层渲染,避免重排导致的掉帧与滚动卡顿。