SSGOI

模糊动画

通过模糊效果平滑地聚焦或模糊元素

模糊动画

模糊(Blur)动画通过对元素应用模糊效果来切换焦点或柔化背景。它提供了视觉深度和优雅的过渡效果。

基本用法

import { transition } from '@ssgoi/react';
import { blur } from '@ssgoi/react/transitions';

function Component() {
  const [isVisible, setIsVisible] = useState(true);
  
  return (
    <div>
      {isVisible && (
        <div ref={transition({ key: 'blur-element', ...blur() })}>
          应用了模糊动画的元素
        </div>
      )}
    </div>
  );
}

选项

interface BlurOptions {
  amount?: number | string;  // 模糊强度(默认:10)
  opacity?: number;          // 起始透明度(默认:0)
  scale?: boolean;           // 添加缩放效果(默认:false)
  fade?: boolean;            // 添加淡入淡出效果(默认:true)
  spring?: {
    stiffness?: number;      // 弹簧刚度(默认:300)
    damping?: number;        // 阻尼系数(默认:30)
  };
}

选项说明

  • amount: 模糊的强度(像素单位或CSS值)
  • opacity: 起始透明度(0-1)
  • scale: 是否与模糊一起应用缩放效果
  • fade: 是否与模糊一起应用淡入淡出效果
  • spring: 弹簧物理设置

使用示例

强模糊效果

const heavyBlur = blur({
  amount: 20,  // 强模糊
  spring: { stiffness: 200, damping: 25 }
});

<div ref={transition({ key: 'heavy-blur', ...heavyBlur })}>
  强烈模糊的元素
</div>

模糊+缩放组合

const blurScale = blur({
  amount: 15,
  scale: true,  // 添加缩放效果
  spring: { stiffness: 400, damping: 35 }
});

<div ref={transition({ key: 'blur-scale', ...blurScale })}>
  模糊并缩小的效果
</div>

仅模糊(无淡入淡出)

const blurOnly = blur({
  fade: false,     // 移除淡入淡出效果
  opacity: 1,      // 保持完全不透明
  amount: '2rem'   // 使用rem单位
});

<div ref={transition({ key: 'blur-only', ...blurOnly })}>
  仅应用模糊而无透明度变化
</div>

实用示例

背景模糊效果

function BlurredBackground() {
  const [isModalOpen, setIsModalOpen] = useState(false);
  
  return (
    <div className="relative">
      {/* 背景内容 */}
      <div className="p-8">
        <h1>主要内容</h1>
        <button onClick={() => setIsModalOpen(true)}>
          打开模态框
        </button>
      </div>
      
      {/* 模糊遮罩 */}
      {isModalOpen && (
        <div 
          ref={transition({ 
            key: 'blur-overlay', 
            ...blur({ amount: 8, opacity: 0.5 }) 
          })}
          className="fixed inset-0 bg-black/20"
          onClick={() => setIsModalOpen(false)}
        />
      )}
    </div>
  );
}

图片加载效果

function BlurredImage({ src, alt }) {
  const [isLoaded, setIsLoaded] = useState(false);
  
  return (
    <div className="relative">
      {/* 占位符 */}
      {!isLoaded && (
        <div 
          ref={transition({ 
            key: 'image-placeholder', 
            ...blur({ amount: 20 }) 
          })}
          className="absolute inset-0 bg-gray-200"
        />
      )}
      
      {/* 实际图片 */}
      <img
        src={src}
        alt={alt}
        onLoad={() => setIsLoaded(true)}
        className={isLoaded ? 'opacity-100' : 'opacity-0'}
      />
    </div>
  );
}

焦点切换效果

function FocusableCards() {
  const [focusedId, setFocusedId] = useState(null);
  
  return (
    <div className="grid grid-cols-3 gap-4">
      {[1, 2, 3].map(id => (
        <div
          key={id}
          onClick={() => setFocusedId(id)}
          className="relative cursor-pointer"
        >
          {/* 模糊效果 */}
          {focusedId && focusedId !== id && (
            <div 
              ref={transition({ 
                key: `blur-${id}`, 
                ...blur({ amount: 5, opacity: 0.7 }) 
              })}
              className="absolute inset-0 z-10"
            />
          )}
          
          {/* 卡片内容 */}
          <div className="p-6 bg-white rounded-lg shadow">
            <h3>卡片 {id}</h3>
            <p>点击聚焦</p>
          </div>
        </div>
      ))}
    </div>
  );
}

高级用法

动态模糊强度

function DynamicBlur() {
  const [blurAmount, setBlurAmount] = useState(10);
  
  const dynamicBlur = blur({
    amount: blurAmount,
    spring: { stiffness: 300, damping: 30 }
  });
  
  return (
    <div>
      <input
        type="range"
        min="0"
        max="30"
        value={blurAmount}
        onChange={(e) => setBlurAmount(Number(e.target.value))}
      />
      
      <div ref={transition({ key: `blur-${blurAmount}`, ...dynamicBlur })}>
        模糊强度:{blurAmount}px
      </div>
    </div>
  );
}

文本遮挡

function Spoiler({ children }) {
  const [isRevealed, setIsRevealed] = useState(false);
  
  return (
    <span 
      className="relative inline-block cursor-pointer"
      onClick={() => setIsRevealed(!isRevealed)}
    >
      {!isRevealed && (
        <span 
          ref={transition({ 
            key: 'spoiler-blur', 
            ...blur({ amount: 8, fade: false }) 
          })}
          className="absolute inset-0"
        />
      )}
      <span className={!isRevealed ? 'select-none' : ''}>
        {children}
      </span>
    </span>
  );
}

性能考虑

  • 模糊效果使用GPU加速,但比其他效果计算量更大
  • 在大面积或多个元素同时应用时可能会影响性能
  • 建议在移动设备上降低模糊强度

性能优化提示

// 移动端适配
const isMobile = window.innerWidth < 768;
const optimizedBlur = blur({
  amount: isMobile ? 5 : 15,  // 移动端降低模糊强度
  spring: { 
    stiffness: isMobile ? 400 : 300,  // 移动端加快动画
    damping: 35 
  }
});

浏览器兼容性

  • 所有现代浏览器都支持
  • Safari可能需要-webkit-backdrop-filter
  • IE11不支持CSS滤镜

推荐使用场景

  • 模态框/对话框:模糊背景内容
  • 图片加载:从占位符过渡到实际图片
  • 焦点效果:强调重要元素
  • 剧透文本:点击前隐藏内容
  • 深度表现:区分UI层级