基础实现(最简单)

这是最直接的方法,适合快速理解和入门。

flash水滴 网页上冒出的水滴效果
(图片来源网络,侵删)

HTML 结构

只需要一个容器来包裹所有水滴,这样水滴就可以相对于这个容器定位。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">水滴效果</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>在页面上移动鼠标试试看!</h1>
    <p>水滴会跟随你的鼠标出现。</p>
    <div id="ripple-container"></div>
    <script src="script.js"></script>
</body>
</html>

CSS 样式

我们为水滴元素(.ripple)定义样式和动画。

/* body 和容器样式 */
body {
    font-family: sans-serif;
    background-color: #282c34;
    color: white;
    height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    overflow: hidden; /* 防止页面滚动条出现 */
    cursor: none; /* 可选:隐藏默认鼠标指针 */
}
#ripple-container {
    position: fixed; /* 固定定位,覆盖整个视口 */
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none; /* 关键:让容器不拦截鼠标事件,事件可以穿透到下方 */
}
/* 水滴样式 */
.ripple {
    position: absolute;
    border-radius: 50%; /* 圆形 */
    background-color: rgba(255, 255, 255, 0.7); /* 半透明白色 */
    transform: scale(0); /* 初始状态为0大小 */
    animation: ripple-animation 0.6s linear;
    pointer-events: none; /* 水滴本身也不拦截事件 */
}
/* 定义水滴的扩散和消失动画 */
@keyframes ripple-animation {
    to {
        transform: scale(4); /* 放大到4倍 */
        opacity: 0; /* 完全透明 */
    }
}

JavaScript 逻辑

这是实现效果的核心,监听鼠标移动事件,创建水滴元素并应用动画。

document.addEventListener('DOMContentLoaded', () => {
    const container = document.getElementById('ripple-container');
    // 监听整个文档的鼠标移动事件
    document.addEventListener('mousemove', (e) => {
        // 1. 创建一个新的水滴元素
        const ripple = document.createElement('div');
        ripple.classList.add('ripple');
        // 2. 设置水滴的初始位置(鼠标点击的位置)
        // 使用 clientX 和 clientY 获取相对于视口的坐标
        const size = 20; // 水滴的初始大小
        ripple.style.width = `${size}px`;
        ripple.style.height = `${size}px`;
        // 计算水滴的中心点对准鼠标位置
        ripple.style.left = `${e.clientX - size / 2}px`;
        ripple.style.top = `${e.clientY - size / 2}px`;
        // 3. 将水滴添加到容器中
        container.appendChild(ripple);
        // 4. 动画结束后移除水滴,防止DOM元素堆积
        // 这一步对于性能至关重要!
        ripple.addEventListener('animationend', () => {
            ripple.remove();
        });
    });
});

进阶实现(点击触发,更炫酷)

这个版本模仿了很多现代网站的效果,水滴只在点击时产生,并且颜色可以随机,或者根据背景色变化。

flash水滴 网页上冒出的水滴效果
(图片来源网络,侵删)

HTML 结构

和基础版本类似,只是提示文字变了。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">点击水滴效果</title>
    <link rel="stylesheet" href="advanced-style.css">
</head>
<body>
    <h1>点击页面任意位置!</h1>
    <p>每次点击都会产生一个彩色水滴。</p>
    <div id="ripple-container"></div>
    <script src="advanced-script.js"></script>
</body>
</html>

CSS 样式

这里我们让水滴的颜色和大小随机,视觉效果更丰富。

/* body 和容器样式与基础版类似 */
body {
    font-family: sans-serif;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); /* 渐变背景 */
    color: white;
    height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    overflow: hidden;
    cursor: pointer; /* 提示用户可以点击 */
}
#ripple-container {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}
/* 水滴样式,颜色和大小将由JS动态设置 */
.ripple {
    position: absolute;
    border-radius: 50%;
    transform: scale(0);
    animation: ripple-animation 0.6s ease-out;
    pointer-events: none;
    background: radial-gradient(circle, rgba(255,255,255,0.8) 0%, rgba(255,255,255,0) 70%);
}
@keyframes ripple-animation {
    to {
        transform: scale(10); /* 放大倍数可以更大 */
        opacity: 0;
    }
}

JavaScript 逻辑

修改为监听 click 事件,并动态生成随机的颜色和大小。

document.addEventListener('DOMContentLoaded', () => {
    const container = document.getElementById('ripple-container');
    // 监听整个文档的点击事件
    document.addEventListener('click', (e) => {
        const ripple = document.createElement('div');
        ripple.classList.add('ripple');
        // 随机大小 (20px 到 100px)
        const size = Math.random() * 80 + 20;
        ripple.style.width = `${size}px`;
        ripple.style.height = `${size}px`;
        // 随机颜色 (使用 HSL 色彩模式更容易生成鲜艳的颜色)
        const hue = Math.floor(Math.random() * 360);
        // 使用 HSL 颜色,并设置一定的透明度
        ripple.style.background = `hsla(${hue}, 100%, 70%, 0.7)`;
        // 计算位置,让水滴中心对准点击位置
        ripple.style.left = `${e.clientX - size / 2}px`;
        ripple.style.top = `${e.clientY - size / 2}px`;
        container.appendChild(ripple);
        // 动画结束后移除
        ripple.addEventListener('animationend', () => {
            ripple.remove();
        });
    });
});

关键点解析

  1. pointer-events: none:这个CSS属性非常重要,它告诉浏览器这个元素不响应鼠标事件(如点击、悬停),这样,鼠标事件就能穿透水滴,继续传递到页面上的其他元素(如果有的话),或者在我们的例子中,就是传递到 document 上,从而保证每次点击或移动都能产生新的水滴。

    flash水滴 网页上冒出的水滴效果
    (图片来源网络,侵删)
  2. animationend 事件:在基础和进阶版本中,我们都监听了这个事件,动画结束后,我们手动调用 element.remove() 来删除DOM节点,如果不这样做,随着用户不断点击或移动,页面上会堆积成百上千个看不见的 .ripple 元素,严重影响浏览器性能,甚至可能导致页面卡死。

  3. 定位:我们使用 position: absoluteleft/top 来定位水滴,因为它的父容器 #ripple-containerposition: fixed,所以水滴是相对于整个视口进行定位的,而不是相对于页面上的其他内容。

  4. 性能优化

    • 移除DOM元素:如上所述,这是最关键的一步。
    • 使用 requestAnimationFrame:对于非常频繁的鼠标移动事件(比如方案一),可以考虑使用 requestAnimationFrame 来节流,避免在短时间内创建过多水滴,但对于大多数情况,直接监听 mousemove 并配合 animationend 移除已经足够流畅。
特性 基础版 (鼠标移动) 进阶版 (鼠标点击)
触发事件 mousemove click
视觉效果 单一白色水滴 随机颜色和大小的水滴
适用场景 背景装饰,跟随光标 按钮点击反馈,页面交互
核心代码 在鼠标位置创建元素,动画后移除 在点击位置创建元素,动画后移除

你可以根据你的具体需求选择合适的方案,或者将两者结合,创造出更有趣的交互效果,希望这个详细的教程能帮助你实现想要的水滴效果!