最近业余时间在探索 claude code 的使用,用了一个一键转换液态水滴效果的 promot,感觉还不错,距离 iOS 的差远了,但是能用。分享一波,大家需要自取。
为我的 Web 项目添加液态水滴交互效果,采用简约清新的视觉风格,使用轻量级 CSS 动画和最小化 JavaScript 实现。要求完美融入现有设计,保持高性能。
请实现以下 4 个核心效果:
应用元素:
li、.list-item、.card 等)效果描述:
技术要求:
::before 和 ::after 伪元素实现双层波纹radial-gradient 径向渐变模拟液态扩散position: relative 和 overflow: 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%);
应用元素:
button、.btn、.button 等)效果描述:
技术要求:
CSS 部分:
::before 伪元素实现点击波纹::after 伪元素实现悬停光晕--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%);
应用元素:
.container、.wrapper、main 等)效果描述:
技术要求:
::before 和 ::after 伪元素position: relative
z-index: -1 确保在内容后方filter: blur() 增强液态感(6-8px)动画路径示例:
@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%);
应用元素:
效果描述:
技术要求:
border-radius 语法实现水滴形状border-radius: 水平半径 / 垂直半径
上左 上右 下右 下左
形状参数参考:
/* 小元素(按钮) */
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;
}
请确保实现以下性能优化措施:
/* 对所有动画伪元素应用 */
.element::before,
.element::after {
transform: translateZ(0);
backface-visibility: hidden;
will-change: transform, opacity;
}
/* 对有液态效果的元素应用 */
.element {
contain: layout style paint;
}
/* 响应用户系统偏好 */
@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) - 科技蓝rgba(168, 239, 133, 0.3) - 淡绿rgba(255, 255, 255, 0.6) - 白色请按照以下步骤实施:
::before/::after 使用/* ==================== 液态水滴效果 ==================== */
/* 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) { /* 降级 */ }
// ==================== 液态波纹效果 ====================
/**
* 为按钮添加液态波纹效果
*/
function addLiquidRippleEffect() {
// 实现代码
}
/**
* 触发按钮波纹动画
* @param {HTMLElement} button - 按钮元素
* @param {MouseEvent} event - 点击事件
*/
function triggerButtonRipple(button, event) {
// 实现代码
}
// 页面加载时初始化
document.addEventListener('DOMContentLoaded', addLiquidRippleEffect);
实现完成后,请确保满足以下标准:
如果列表项或按钮是动态创建的:
// 方案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);
}
}
A: 检查元素是否已经使用了 ::before/::after 伪元素。如果冲突,可以:
<div> 元素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);
}
A:
@media (hover: none) 禁用悬停效果A:
.no-liquid::before,
.no-liquid::after {
display: none !important;
animation: none !important;
}
prefers-reduced-motion 支持