1. 基础版:使用纯CSS实现,简单、轻量,适合初学者。
  2. 进阶版:使用原生JavaScript实现,效果更丰富、更流畅,可定制性更高。

纯CSS实现(简单快捷)

这种方案的核心思想是利用 hover 伪类和CSS动画,当鼠标移动到特定元素上时,生成带有动画的音乐符。

效果预览

当鼠标悬停在下方区域时,会出现一个向上飘动的音乐符。

代码实现

你只需要将以下代码保存为一个 .html 文件,然后用浏览器打开即可。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">CSS 鼠标音乐符特效</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            background-color: #f0f2f5;
            color: #333;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            overflow: hidden; /* 防止音乐符飘出时出现滚动条 */
        }
        .container {
            text-align: center;
            padding: 40px;
            background-color: white;
            border-radius: 10px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
        }
        .container h1 {
            color: #007bff;
        }
        .container p {
            color: #666;
            margin-top: 20px;
        }
        /* 1. 定义音乐符的基本样式 */
        .music-note {
            position: absolute;
            font-size: 2rem; /* 音乐符大小 */
            color: #007bff;  /* 音乐符颜色 */
            pointer-events: none; /* 让鼠标可以穿透音乐符 */
            animation: float-up 1.5s ease-out forwards; /* 应用动画 */
            opacity: 0; /* 初始状态为透明 */
        }
        /* 2. 定义飘动动画 */
        @keyframes float-up {
            0% {
                opacity: 1;     /* 完全可见 */
                transform: translateY(0) scale(0.5); /* 从下方小一点的位置开始 */
            }
            100% {
                opacity: 0;     /* 逐渐消失 */
                transform: translateY(-100px) scale(1.2); /* 向上飘动并放大一点 */
            }
        }
        /* 3. 定义悬停区域的样式 */
        .hover-area {
            display: inline-block;
            padding: 20px 40px;
            background-color: #e9ecef;
            border-radius: 8px;
            cursor: pointer;
            transition: background-color 0.3s;
        }
        .hover-area:hover {
            background-color: #dee2e6;
        }
        /* 4. 核心:使用伪类在悬停时创建音乐符 */
        .hover-area:hover::before {
            content: '♪'; /* 使用音乐符实体或Emoji ♪ ♫ */
            position: absolute;
            /* 随机位置偏移,让音乐符从不同位置出现 */
            left: calc(50% + (Math.random() * 40 - 20) * 1px);
            top: calc(50% + (Math.random() * 20 - 10) * 1px);
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>鼠标音乐符特效</h1>
        <p>将鼠标移动到下面的灰色方块上</p>
        <div class="hover-area">悬停我</div>
    </div>
</body>
</html>

代码解析

  1. .music-note: 这是音乐符的样式,我们把它设置为绝对定位,这样它就可以脱离正常的文档流,并且可以精确定位。pointer-events: none 是一个关键属性,它确保鼠标事件可以穿透这个音乐符,继续与下方的元素交互。
  2. @keyframes float-up: 定义了一个名为 float-up 的关键帧动画,它控制音乐符从半透明、较小,向上移动并放大,直到完全透明。
  3. .hover-area:hover::before: 这是整个特效的核心。
    • hover 是一个CSS伪类,当鼠标悬停在 .hover-area 元素上时触发。
    • :before 是一个伪元素,允许我们在元素内容之前插入生成的内容。
    • content: '♪':我们在这里插入音乐符,你也可以使用 或者其他符号。
    • 通过 lefttop 的随机偏移,让每次出现的音乐符位置略有不同,增加趣味性。

原生JavaScript实现(效果更佳)

JavaScript方案可以实现更复杂的交互,

  • 真正的鼠标跟随:音乐符从鼠标位置出现,而不是从悬停区域的中心。
  • 连续生成:鼠标移动时可以连续不断地产生音乐符。
  • 更丰富的动画:可以控制音乐符的生成频率、速度、颜色等。

效果预览

当鼠标在整个页面上移动时,会持续不断地从鼠标位置生成向上飘动的音乐符。

代码实现

同样,将以下代码保存为 .html 文件即可。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">JavaScript 鼠标音乐符特效</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            background-color: #1a1a2e;
            color: #eee;
            height: 100vh;
            margin: 0;
            overflow: hidden; /* 防止滚动条 */
            cursor: none; /* 隐藏默认鼠标指针 */
        }
        /* 音乐符的样式 */
        .music-note {
            position: fixed; /* 相对于视口定位,即使页面滚动也能保持在正确位置 */
            color: #f39c12; /* 橙色音乐符 */
            pointer-events: none; /* 鼠标穿透 */
            user-select: none; /* 防止用户选中 */
            z-index: 9999; /* 确保音乐符在最上层 */
            animation: float-up 2s ease-out forwards;
        }
        /* 飘动和淡出动画 */
        @keyframes float-up {
            0% {
                opacity: 1;
                transform: translateY(0) rotate(0deg);
            }
            100% {
                opacity: 0;
                transform: translateY(-150px) rotate(20deg); /* 向上飘并旋转 */
            }
        }
        /* 自定义鼠标指针样式 */
        .custom-cursor {
            position: fixed;
            width: 20px;
            height: 20px;
            border: 2px solid #f39c12;
            border-radius: 50%;
            pointer-events: none;
            z-index: 10000;
            transition: transform 0.1s ease-out;
            transform: translate(-50%, -50%);
        }
    </style>
</head>
<body>
    <!-- 自定义鼠标指针 -->
    <div class="custom-cursor" id="cursor"></div>
    <script>
        // 1. 获取页面元素
        const body = document.body;
        const cursor = document.getElementById('cursor');
        // 音乐符数组,可以随机选择
        const musicNotes = ['♪', '♫', '♬', '♩', '♭', '♯'];
        // 控制生成频率的变量
        let lastNoteTime = 0;
        const noteInterval = 100; // 每100毫秒最多生成一个音符
        // 2. 监听鼠标移动事件
        document.addEventListener('mousemove', (e) => {
            // 更新自定义指针的位置
            cursor.style.left = e.clientX + 'px';
            cursor.style.top = e.clientY + 'px';
            // 获取当前时间
            const currentTime = Date.now();
            // 如果距离上次生成音符的时间大于设定的间隔,则生成新音符
            if (currentTime - lastNoteTime > noteInterval) {
                createMusicNote(e.clientX, e.clientY);
                lastNoteTime = currentTime;
            }
        });
        // 3. 创建音符的函数
        function createMusicNote(x, y) {
            // 创建一个 div 元素作为音符
            const note = document.createElement('div');
            note.className = 'music-note';
            // 随机选择一个音符
            const randomNote = musicNotes[Math.floor(Math.random() * musicNotes.length)];
            note.textContent = randomNote;
            // 设置音符的初始位置(鼠标位置)
            note.style.left = x + 'px';
            note.style.top = y + 'px';
            // 随机化音符的大小和颜色,增加变化
            const size = Math.random() * 1.5 + 0.5; // 0.5 到 2 之间的大小
            const hue = Math.random() * 60 + 30; // 30 到 90 之间的色相,主要是黄橙色系
            note.style.fontSize = `${size}rem`;
            note.style.color = `hsl(${hue}, 100%, 60%)`;
            // 将音符添加到 body 中
            body.appendChild(note);
            // 动画结束后,移除音符元素,避免DOM元素堆积
            note.addEventListener('animationend', () => {
                note.remove();
            });
        }
        // 鼠标进入和离开页面时,显示/隐藏自定义指针
        document.addEventListener('mouseenter', () => {
            cursor.style.opacity = '1';
        });
        document.addEventListener('mouseleave', () => {
            cursor.style.opacity = '0';
        });
    </script>
</body>
</html>

代码解析

  1. HTML: 在 <body> 中添加了一个 <div id="cursor"> 作为我们自定义的鼠标指针。
  2. CSS:
    • .music-note: 使用 position: fixed 确保音符相对于浏览器窗口定位,这样即使页面很长,音符也能正确飘动。
    • @keyframes: 在动画结束时加入了 rotate,让音符有旋转效果,更生动。
    • .custom-cursor: 自定义指针的样式,transform: translate(-50%, -50%) 是一个常用技巧,可以让元素的中心对准鼠标坐标。
  3. JavaScript:
    • 事件监听: document.addEventListener('mousemove', ...) 监听整个页面的鼠标移动。
    • 节流: lastNoteTimenoteInterval 实现了一个简单的节流机制,如果每次 mousemove 都生成音符,会导致性能问题,这个机制确保音符生成频率不会过高,让动画更流畅。
    • createMusicNote 函数:
      • 使用 document.createElement('div') 动态创建DOM元素。
      • 随机选择 musicNotes 数组中的符号,增加视觉多样性。
      • 随机设置音符的大小和颜色 (hsl 色彩模式非常适合生成随机但和谐的颜色)。
      • 关键: note.addEventListener('animationend', ...) 在CSS动画结束后,调用 note.remove() 来删除这个DOM元素,这对于长时间运行的页面至关重要,否则页面会堆积成千上万的元素,最终导致卡顿甚至崩溃。

如何选择?

  • 选择CSS方案:如果你的需求非常简单,只需要在某个按钮或链接上添加一个微交互,并且不想引入任何JavaScript,那么CSS方案是最佳选择,它简单、性能好。
  • 选择JavaScript方案:如果你想要一个更酷、更动态的全屏效果,或者希望特效与鼠标的实时位置紧密相关,那么JavaScript方案是更强大的选择,它提供了极高的灵活性和控制力。

希望这两个方案能帮助你实现想要的音乐符特效!