wui
组件

渐进模糊 Progressive Blur

使用多层渐变遮罩构建方向可控的渐进式背景模糊。

基础示例

Loading…
pnpm dlx wui@latest add @wui/progressive-blur
components/ui/progressive-blur.tsx
"use client"

import * as React from "react"
import { motion, type HTMLMotionProps } from "motion/react"

import { cn } from "@/lib/utils"

const gradientAngles = {
  top: 0,
  right: 90,
  bottom: 180,
  left: 270,
} as const

export interface ProgressiveBlurProps extends HTMLMotionProps<"div"> {
  /** Edge that receives the strongest blur. @default "bottom" */
  direction?: keyof typeof gradientAngles
  /** Number of overlapping mask bands. Values below 2 are clamped. @default 8 */
  blurLayers?: number
  /** Blur added by each successive layer in pixels. @default 0.25 */
  blurIntensity?: number
}

function ProgressiveBlur({
  direction = "bottom",
  blurLayers = 8,
  blurIntensity = 0.25,
  className,
  ...props
}: ProgressiveBlurProps) {
  const layers = Math.max(Math.round(blurLayers), 2)
  const segmentSize = 1 / (layers + 1)
  const angle = gradientAngles[direction]

  return (
    <div
      aria-hidden="true"
      data-slot="progressive-blur"
      className={cn("pointer-events-none relative", className)}
    >
      {Array.from({ length: layers }, (_, index) => {
        const stops = [index, index + 1, index + 2, index + 3].map(
          (position, stopIndex) =>
            `rgba(0, 0, 0, ${stopIndex === 1 || stopIndex === 2 ? 1 : 0}) ${position * segmentSize * 100}%`
        )
        const maskImage = `linear-gradient(${angle}deg, ${stops.join(", ")})`
        const blur = Math.max(0, index * blurIntensity)

        return (
          <motion.div
            key={index}
            data-slot="progressive-blur-layer"
            className="absolute inset-0 rounded-[inherit]"
            style={{
              maskImage,
              WebkitMaskImage: maskImage,
              backdropFilter: `blur(${blur}px)`,
              WebkitBackdropFilter: `blur(${blur}px)`,
            }}
            {...props}
          />
        )
      })}
    </div>
  )
}

export { ProgressiveBlur, gradientAngles }

组件作用

ProgressiveBlur 将多个带渐变 mask 的 backdrop-filter 图层叠加起来,使模糊强度沿某个方向逐步增加。它适合滚动容器边缘、图片文字交界处和固定操作栏后方,用来建立内容层级而不是遮盖信息。

组件仅负责视觉效果,默认忽略指针事件并从无障碍树隐藏。父容器通常需要 position: relative 与明确尺寸。

组件属性

PropTypeDefaultDescription
direction"top" | "right" | "bottom" | "left"bottomEdge that receives the strongest blur.
blurLayersnumber8Number of overlapping mask bands. Values below 2 are clamped.
blurIntensitynumber0.25Blur added by each successive layer in pixels.

事件

组件透传 Motion div 的动画与原生指针事件属性。由于它默认用于纯装饰层,一般不应在模糊图层本身绑定交互。

扩展使用

使用 direction 将最强模糊放在 toprightbottomleft。增加 blurLayers 会让过渡更细腻但也提高渲染成本;优先从 6–10 层和较低的 blurIntensity 开始调整。