FunTester 液态水滴效果实现 Prompt 分享

FunTester · December 24, 2025 · 598 hits

最近业余时间在探索 claude code 的使用,用了一个一键转换液态水滴效果的 promot,感觉还不错,距离 iOS 的差远了,但是能用。分享一波,大家需要自取。

任务:实现简约清新风格的液态水滴效果

目标

为我的 Web 项目添加液态水滴交互效果,采用简约清新的视觉风格,使用轻量级 CSS 动画和最小化 JavaScript 实现。要求完美融入现有设计,保持高性能。

效果需求清单

请实现以下 4 个核心效果:

1. 列表项/卡片的液态扩散效果

应用元素:

  • 列表项(li.list-item.card 等)
  • 可交互的卡片组件

效果描述:

  • 鼠标悬停时,从元素中心产生双层液态波纹向外扩散
  • 第一层(快速波纹):科技蓝色,1.2 秒扩散到元素的 300% 大小
  • 第二层(慢速波纹):淡绿色,1.5 秒扩散到元素的 250% 大小,延迟 0.2 秒启动
  • 活跃/选中状态的元素:持续液态脉冲效果(3 秒循环)

技术要求:

  • 使用 ::before::after 伪元素实现双层波纹
  • 使用 radial-gradient 径向渐变模拟液态扩散
  • 波纹从透明度 0 → 1 → 0 变化,同时缩放从 0.8 → 1.2
  • 父元素需要 position: relativeoverflow: hidden
  • 确保内容在伪元素之上(z-index: 1

色彩参考:

/* 快速波纹 - 科技蓝 */
background: radial-gradient(circle, rgba(0, 234, 255, 0.4) 0%, transparent 70%);

/* 慢速波纹 - 淡绿 */
background: radial-gradient(circle, rgba(168, 239, 133, 0.3) 0%, transparent 70%);

2. 按钮的液态波纹效果

应用元素:

  • 所有按钮元素(button.btn.button 等)

效果描述:

  • 点击效果: 从精确的点击位置产生白色波纹向外扩散(0.5 秒)
  • 悬停效果: 产生持续的液态光晕效果(2 秒循环)

技术要求:

CSS 部分:

  • 使用 ::before 伪元素实现点击波纹
  • 使用 ::after 伪元素实现悬停光晕
  • 波纹起点通过 CSS 自定义属性控制:--ripple-x--ripple-y
  • 添加 .ripple-active 类时触发波纹动画

JavaScript 部分:

// 为按钮添加波纹效果
function addLiquidRippleEffect() {
    const buttons = document.querySelectorAll('button, .btn, .button');

    buttons.forEach(button => {
        button.addEventListener('click', function(e) {
            // 计算点击位置
            const rect = this.getBoundingClientRect();
            const x = e.clientX - rect.left;
            const y = e.clientY - rect.top;

            // 设置波纹起点
            this.style.setProperty('--ripple-x', `${x}px`);
            this.style.setProperty('--ripple-y', `${y}px`);

            // 触发波纹动画
            this.classList.remove('ripple-active');
            requestAnimationFrame(() => {
                this.classList.add('ripple-active');
                setTimeout(() => this.classList.remove('ripple-active'), 500);
            });
        });
    });
}

// 页面加载时初始化
document.addEventListener('DOMContentLoaded', addLiquidRippleEffect);

色彩参考:

/* 点击波纹 - 白色 */
background: radial-gradient(circle, rgba(255, 255, 255, 0.6) 0%, transparent 70%);

/* 悬停光晕 - 科技蓝 */
background: radial-gradient(circle, rgba(0, 234, 255, 0.3) 0%, transparent 60%);

3. 背景装饰液态水滴

应用元素:

  • 主容器(.container.wrappermain 等)
  • 侧边栏、导航栏等大面积区域

效果描述:

  • 在容器背景中添加 2 个装饰性水滴,缓慢浮动
  • 大水滴:科技蓝色,120px × 120px,15 秒循环
  • 中水滴:淡绿色,80px × 80px,18 秒循环
  • 水滴形状动态变化(border-radius 动画)+ 位移 + 旋转

技术要求:

  • 使用容器的 ::before::after 伪元素
  • 父元素需要 position: relative
  • 水滴设置 z-index: -1 确保在内容后方
  • 使用 filter: blur() 增强液态感(6-8px)
  • 透明度设置为 0.6-0.7,避免遮挡内容

动画路径示例:

@keyframes liquid-float {
    0%, 100% {
        transform: translate(0, 0) rotate(0deg);
        border-radius: 45% 55% 50% 50% / 55% 45% 55% 45%;
    }
    25% {
        transform: translate(15px, -20px) rotate(5deg);
        border-radius: 50% 50% 45% 55% / 50% 50% 50% 50%;
    }
    50% {
        transform: translate(0, -35px) rotate(0deg);
        border-radius: 55% 45% 50% 50% / 45% 55% 45% 55%;
    }
    75% {
        transform: translate(-15px, -20px) rotate(-5deg);
        border-radius: 50% 50% 55% 45% / 55% 45% 50% 50%;
    }
}

色彩参考:

/* 大水滴 - 科技蓝 */
background: radial-gradient(ellipse at 30% 30%,
    rgba(0, 234, 255, 0.15) 0%,
    rgba(0, 234, 255, 0.08) 50%,
    transparent 80%);

/* 中水滴 - 淡绿 */
background: radial-gradient(ellipse at 40% 40%,
    rgba(168, 239, 133, 0.12) 0%,
    rgba(168, 239, 133, 0.06) 50%,
    transparent 80%);

4. 元素形状改造(水滴形状)

应用元素:

  • 所有需要液态效果的元素(列表项、按钮、卡片等)

效果描述:

  • 将标准圆角改为水滴形状(上部较圆润,下部略尖)
  • 悬停时形状轻微变化
  • 选中/活跃状态持续形状脉冲动画

技术要求:

  • 使用复杂的 border-radius 语法实现水滴形状
  • 语法格式:border-radius: 水平半径 / 垂直半径
  • 每个方向 4 个值:上左 上右 下右 下左

形状参数参考:

/* 小元素(按钮) */
border-radius: 15px 15px 18px 18px / 15px 15px 20px 20px;

/* 中等元素(列表项) */
border-radius: 20px 20px 25px 25px / 20px 20px 30px 30px;

/* 悬停时 */
border-radius: 25px 25px 30px 30px / 25px 25px 35px 35px;

形变动画示例:

@keyframes droplet-morph {
    0%, 100% {
        border-radius: 22px 22px 26px 26px / 22px 22px 30px 30px;
    }
    25% {
        border-radius: 24px 20px 28px 24px / 24px 20px 32px 28px;
    }
    50% {
        border-radius: 20px 24px 24px 28px / 20px 24px 28px 32px;
    }
    75% {
        border-radius: 24px 22px 26px 26px / 24px 22px 30px 30px;
    }
}

/* 应用到悬停状态 */
.element:hover {
    animation: droplet-morph 1.5s ease-in-out infinite;
}

性能优化要求

请确保实现以下性能优化措施:

1. GPU 硬件加速

/* 对所有动画伪元素应用 */
.element::before,
.element::after {
    transform: translateZ(0);
    backface-visibility: hidden;
    will-change: transform, opacity;
}

2. 渲染范围限制

/* 对有液态效果的元素应用 */
.element {
    contain: layout style paint;
}

3. 低性能设备降级

/* 响应用户系统偏好 */
@media (prefers-reduced-motion: reduce) {
    .element::before,
    .element::after {
        animation: none !important;
        transition: none !important;
    }
}

动画时序规范

请使用以下标准时序:

| 效果类型 | 持续时间 | 缓动函数 | 循环 |
| ------------ | ----------- | -------- |
| 快速波纹扩散 | 1.2s | ease-out | infinite |
| 慢速波纹扩散 | 1.5s | ease-out | infinite |
| 点击波纹 | 0.5s | ease-out | once |
| 悬停光晕 | 2s | ease-in-out | infinite |
| 液态脉冲 | 3s | ease-in-out | infinite |
| 水滴浮动 | 15-18s | ease-in-out | infinite |
| 形状形变 | 1.5s | ease-in-out | infinite |

推荐缓动函数:

/* 自然流动感 */
transition: all 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94);

/* 柔和渐入渐出 */
animation: xxx ease-in-out infinite;

色彩方案建议

如果我的项目有现有配色,请根据以下规则调整:

主液态色(快速波纹)

  • 默认: rgba(0, 234, 255, 0.4) - 科技蓝
  • 替换规则: 使用项目主色,透明度 0.3-0.5

辅助液态色(慢速波纹)

  • 默认: rgba(168, 239, 133, 0.3) - 淡绿
  • 替换规则: 使用项目辅助色或主色的邻近色,透明度 0.2-0.4

装饰水滴

  • 默认: 主色和辅助色,透明度 0.1-0.15
  • 替换规则: 使用更低透明度的项目配色

点击波纹

  • 默认: rgba(255, 255, 255, 0.6) - 白色
  • 替换规则: 深色主题用白色,浅色主题用深色或主色

实现步骤

请按照以下步骤实施:

第一步:准备工作

  1. 识别项目中需要添加液态效果的元素(列表项、按钮、容器等)
  2. 确认项目的主色调和辅助色
  3. 检查现有 CSS 是否有冲突的 ::before/::after 使用

第二步:实现核心效果

  1. 先实现列表项/卡片的液态扩散效果(最重要)
  2. 然后实现按钮的液态波纹效果(需要 JS 配合)
  3. 添加背景装饰水滴(可选,但建议添加)
  4. 最后改造元素形状为水滴形状

第三步:优化和测试

  1. 添加性能优化代码(GPU 加速、Containment)
  2. 添加低性能设备降级方案
  3. 在不同浏览器测试效果
  4. 检查帧率是否保持 60fps

第四步:细节调整

  1. 根据实际效果调整动画时长
  2. 微调色彩透明度以匹配项目风格
  3. 调整水滴形状参数以适应元素尺寸
  4. 确保所有交互反馈流畅自然

代码组织建议

CSS 文件结构

/* ==================== 液态水滴效果 ==================== */

/* 1. 列表项液态扩散效果 */
.list-item { /* 基础样式 */ }
.list-item::before { /* 快速波纹 */ }
.list-item::after { /* 慢速波纹 */ }
.list-item:hover::before { /* 悬停触发 */ }
.list-item:hover::after { /* 悬停触发 */ }
@keyframes liquid-ripple { /* 波纹动画 */ }

/* 2. 按钮液态波纹效果 */
button { /* 基础样式 */ }
button::before { /* 点击波纹 */ }
button::after { /* 悬停光晕 */ }
button.ripple-active::before { /* 波纹激活 */ }
@keyframes liquid-glow { /* 光晕动画 */ }

/* 3. 背景装饰水滴 */
.container::before { /* 大水滴 */ }
.container::after { /* 中水滴 */ }
@keyframes liquid-float-1 { /* 浮动动画1 */ }
@keyframes liquid-float-2 { /* 浮动动画2 */ }

/* 4. 水滴形状 */
.liquid-element { /* 水滴形状定义 */ }
.liquid-element:hover { /* 悬停形状变化 */ }
@keyframes droplet-morph { /* 形变动画 */ }

/* 5. 性能优化 */
.liquid-element::before,
.liquid-element::after { /* GPU 加速 */ }
@media (prefers-reduced-motion: reduce) { /* 降级 */ }

JavaScript 文件结构

// ==================== 液态波纹效果 ====================

/**
 * 为按钮添加液态波纹效果
 */
function addLiquidRippleEffect() {
    // 实现代码
}

/**
 * 触发按钮波纹动画
 * @param {HTMLElement} button - 按钮元素
 * @param {MouseEvent} event - 点击事件
 */
function triggerButtonRipple(button, event) {
    // 实现代码
}

// 页面加载时初始化
document.addEventListener('DOMContentLoaded', addLiquidRippleEffect);

验收标准

实现完成后,请确保满足以下标准:

视觉效果

  • ✅ 悬停列表项/卡片时看到双层液态波纹扩散
  • ✅ 点击按钮时看到从点击位置扩散的波纹
  • ✅ 悬停按钮时看到持续的液态光晕
  • ✅ 背景中有缓慢浮动的装饰水滴
  • ✅ 所有元素采用水滴形状
  • ✅ 活跃/选中元素有持续脉冲效果

性能指标

  • ✅ 浏览器帧率保持 60fps
  • ✅ CPU 占用 < 5%
  • ✅ 无明显卡顿或延迟
  • ✅ 在低性能设备上能正常降级

交互体验

  • ✅ 悬停和点击反馈即时响应
  • ✅ 动画流畅自然,无突兀感
  • ✅ 波纹起点准确(按钮点击位置)
  • ✅ 所有状态反馈清晰明确

代码质量

  • ✅ CSS 代码结构清晰,有注释
  • ✅ JavaScript 代码简洁,无冗余
  • ✅ 选择器性能优化(避免深层嵌套)
  • ✅ 兼容主流浏览器(Chrome 88+, Firefox 78+, Safari 14+)

特殊场景处理

动态内容

如果列表项或按钮是动态创建的:

// 方案1:事件委托(推荐)
document.addEventListener('click', function(e) {
    const button = e.target.closest('button, .btn');
    if (button) {
        triggerButtonRipple(button, e);
    }
});

// 方案2:MutationObserver 监听 DOM 变化
const observer = new MutationObserver(() => {
    addLiquidRippleEffect();
});
observer.observe(document.body, { childList: true, subtree: true });

框架集成

React:

import { useEffect, useRef } from 'react';

function ButtonWithRipple({ children, onClick }) {
    const buttonRef = useRef(null);

    const handleClick = (e) => {
        triggerButtonRipple(buttonRef.current, e);
        onClick?.(e);
    };

    return (
        <button ref={buttonRef} onClick={handleClick}>
            {children}
        </button>
    );
}

Vue:

// 自定义指令
app.directive('liquid-ripple', {
    mounted(el) {
        el.addEventListener('click', (e) => {
            triggerButtonRipple(el, e);
        });
    }
});

// 使用
<button v-liquid-ripple>点击我</button>

Angular:

// 自定义指令
@Directive({ selector: '[liquidRipple]' })
export class LiquidRippleDirective {
    @HostListener('click', ['$event'])
    onClick(event: MouseEvent) {
        triggerButtonRipple(this.el.nativeElement, event);
    }
}

常见问题

Q1: 波纹效果与现有样式冲突怎么办?

A: 检查元素是否已经使用了 ::before/::after 伪元素。如果冲突,可以:

  • 改用额外的包装 <div> 元素
  • 调整现有伪元素的用途
  • 使用 JavaScript 动态创建波纹元素

Q2: 如何适配深色主题?

A: 使用 CSS 变量或主题类:

:root {
    --liquid-primary: rgba(0, 234, 255, 0.4);
    --liquid-secondary: rgba(168, 239, 133, 0.3);
}

[data-theme="dark"] {
    --liquid-primary: rgba(100, 200, 255, 0.5);
    --liquid-secondary: rgba(200, 255, 150, 0.4);
}

Q3: 动画在移动设备上卡顿怎么办?

A:

  1. 确保已添加 GPU 加速
  2. 降低装饰水滴数量(移动端只保留 1 个)
  3. 缩短动画时长
  4. 使用 @media (hover: none) 禁用悬停效果

Q4: 如何禁用某些元素的液态效果?

A:

.no-liquid::before,
.no-liquid::after {
    display: none !important;
    animation: none !important;
}

注意事项

  1. 不要过度使用: 只在重要交互元素上应用液态效果
  2. 保持一致性: 同类元素应使用相同的动画参数
  3. 考虑可访问性: 添加 prefers-reduced-motion 支持
  4. 测试多场景: 包括空状态、加载状态、错误状态等
  5. 监控性能: 使用 Chrome DevTools Performance 面板检查
  6. 渐进增强: 确保在不支持的浏览器中基础功能仍可用

FunTester 原创精华
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
No Reply at the moment.
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up