/ 插件 Halo / 17浏览

网页悬浮音乐播放器

很多个人博客、静态网站都缺少专属背景音乐,市面上大部分播放器代码要么卡顿、要么无法拖动、要么贴边隐藏有bug、按钮点击失灵。

全程拆解代码逻辑,教大家自定义修改样式、切换网易云/QQ音乐音源,彻底吃透这款播放器!

成品核心功能亮点

 高颜值UI:磨砂毛玻璃质感+圆角阴影,适配所有博客主题

 智能拖动逻辑:边框区域灵敏拖动,按钮区域自动切换点击状态,互不冲突

 智能贴边隐藏:仅拖动至屏幕最右侧自动完全隐藏,无任何图标露出,干净整洁

 自动开合动画:隐藏状态鼠标靠近自动弹出,操作完鼠标离开延迟缩回,防误触

 自由悬浮定位:可随意拖动至网页任意位置,放在网页中间/左侧永久固定,不会自动缩回

 全平台兼容:支持Halo、WordPress、静态HTML、Vue等所有可注入代码的网站

 多音源适配:可无缝替换网易云、QQ音乐官方外链播放器

源代码(直接复制部署)

这是经过多次调试、修复的最终版本后续会继续优化:

<!-- 仅最右侧边缘自动缩回 · 极简毛玻璃网易云悬浮播放器 -->
<div id="music-drag-container" style="position: fixed; bottom: 24px; right: 8px; z-index: 9999; width: 290px; height: 90px; transition: transform 0.3s ease-in-out;">
  <!-- 拖动手柄:默认透明,鼠标移上去时才变为可拖动 -->
  <div id="drag-handle" style="position: absolute; top: 0; left: 0; width: 95%; height: 95%; z-index: 2; pointer-events: none; cursor: default;"></div>
  
  <!-- 播放器本体 -->
  <div style="position: absolute; top: 0; left: 0; width: 90; height: 120%; border-radius: 16px; overflow: hidden; background: rgba(255,255,255,0.95); backdrop-filter: blur(10px); box-shadow: 0 4px 20px rgba(0,0,0,0.08); display: flex; align-items: center; justify-content: center; border: 1px solid rgba(0,0,0,0.05);">
<!-- 更换成自己歌单的ID= -->
    <iframe 
      src="https://music.163.com/outchain/player?type=0&id=12616213453&auto=0&height=100&bg=ffffff&fg=333333&mini=true" 
      width="100%" 
      height="100%" 
      frameborder="0"
      allowfullscreen
      style="border: none; position: relative; z-index: 1;">
    </iframe>
  </div>
</div>

<script>
const container = document.getElementById('music-drag-container');
const handle = document.getElementById('drag-handle');
let isDragging = false;
let offsetX, offsetY;
let isHidden = false;
let isOverIframe = false;
let hideTimer = null; // 自动缩回的定时器

// 1. 鼠标进入播放器区域:取消缩回,启用拖动
container.addEventListener('mouseenter', function(e) {
  // 鼠标进入时,清除自动缩回定时器
  if (hideTimer) clearTimeout(hideTimer);
  
  // 如果是隐藏状态,鼠标进入就自动弹出
  if (isHidden) {
    container.style.transform = 'translateX(0)';
    isHidden = false;
  }
  // 只有鼠标不在iframe区域时,才启用拖动
  if (!isOverIframe) {
    handle.style.pointerEvents = 'auto';
    handle.style.cursor = 'move';
  }
});

// 2. 鼠标离开播放器区域:仅在最右侧(窗口宽度的80%以上)才自动缩回
container.addEventListener('mouseleave', function() {
  handle.style.pointerEvents = 'none';
  handle.style.cursor = 'default';
  
  // 计算播放器当前位置
  const playerRight = container.offsetLeft + container.offsetWidth;
  const windowWidth = window.innerWidth ;
  
  // 关键修改:只有当播放器在屏幕最右侧(超过窗口宽度的80%)时,才启动自动缩回
  if (playerRight > windowWidth * 0.99) {
    hideTimer = setTimeout(() => {
      if (!isDragging && !isHidden) {
        container.style.transform = `translateX(${windowWidth - playerRight + 180}px)`;
        isHidden = true;
      }
    }, 500); // 延迟500ms缩回,避免误触
  }
});

// 3. 鼠标进入iframe区域:禁用拖动,恢复点击功能
container.querySelector('iframe').addEventListener('mouseenter', function() {
  isOverIframe = true;
  handle.style.pointerEvents = 'none';
  handle.style.cursor = 'pointer';
  // 操作按钮时,也取消自动缩回
  if (hideTimer) clearTimeout(hideTimer);
});

// 4. 鼠标离开iframe区域:恢复可拖动状态
container.querySelector('iframe').addEventListener('mouseleave', function() {
  isOverIframe = false;
  handle.style.pointerEvents = 'auto';
  handle.style.cursor = 'move';
});

// 拖动开始
handle.addEventListener('mousedown', function(e) {
  isDragging = true;
  offsetX = e.clientX - container.offsetLeft;
  offsetY = e.clientY - container.offsetTop;
  container.style.transition = 'none';
  
  // 如果已经隐藏,先恢复位置再拖动
  if (isHidden) {
    container.style.transform = 'translateX(0)';
    isHidden = false;
  }
  // 拖动时取消自动缩回
  if (hideTimer) clearTimeout(hideTimer);
});

// 拖动中
document.addEventListener('mousemove', function(e) {
  if (!isDragging) return;
  
  let x = e.clientX - offsetX;
  let y = e.clientY - offsetY;
  
  // 限制在窗口内拖动,避免完全拖出屏幕
  x = Math.max(-container.offsetWidth + 30, Math.min(x, window.innerWidth - 30));
  y = Math.max(0, Math.min(y, window.innerHeight - container.offsetHeight));
  
  container.style.left = x + 'px';
  container.style.bottom = 'auto';
  container.style.top = y + 'px';
});

// 拖动结束,自动判断是否隐藏
document.addEventListener('mouseup', function() {
  if (!isDragging) return;
  isDragging = false;
  container.style.transition = 'transform 0.3s ease-in-out';
  
  const playerRight = container.offsetLeft + container.offsetWidth;
  const windowWidth = window.innerWidth;
  
  // 如果播放器右侧超出屏幕超过一半,自动隐藏
  if (playerRight > windowWidth - 10) {
    container.style.transform = `translateX(${windowWidth - playerRight + 200}px)`;
    isHidden = true;
  } else {
    container.style.transform = 'translateX(0)';
    isHidden = false;
  }
});
</script>

逐模块代码详细解析(小白必看)

整个播放器分为 HTML样式结构 和 JS交互逻辑 两部分,下面逐段拆解,看懂就能自由修改!

一、HTML+CSS 样式结构(负责外观与布局)

1. 外层容器(整体定位与动画)

html
<div id="music-drag-container" style="position: fixed; bottom: 24px; right: 24px; z-index: 9999; width: 290px; height: 92px; transition: transform 0.3s ease-in-out;">

核心参数解析

 position: fixed:固定悬浮,页面滚动时播放器位置不变

 bottom/right: 24px:默认悬浮在网页右下角,可自由修改距离

 z-index: 9999:最高层级,不会被网页其他内容遮挡

 width/height:播放器尺寸,可自定义调节大小

 transition 0.3s:控制弹出、缩回的动画速度,丝滑过渡不生硬

2. 透明拖动手柄(核心兼容层)

html
<div id="drag-handle" style="position: absolute; top: 0; left: 0; width: 110%; height: 100%; z-index: 2; pointer-events: none; cursor: default;"></div>

核心作用:解决iframe播放器遮挡拖动的千古难题

 默认透明无遮挡,不影响按钮点击

 鼠标在边框空白区自动激活拖动模式

 鼠标在播放按钮区自动失效,保证点击操作正常

3. 播放器美化层(毛玻璃颜值)

html
<div style="position: absolute; top: 0; left: 0; width: 99%; height: 100%; border-radius: 16px; overflow: hidden; background: rgba(255,255,255,0.95); backdrop-filter: blur(10px); box-shadow: 0 4px 20px rgba(0,0,0,0.08); border: 1px solid rgba(0,0,0,0.05);">

颜值参数解析

 border-radius: 16px:圆角设计,告别生硬直角

 backdrop-filter: blur(10px):核心毛玻璃模糊效果

 box-shadow:柔和阴影,悬浮立体感

 overflow: hidden:隐藏iframe超出部分,界面整洁

4. 音源核心(iframe外链播放器)

承载音乐播放的核心,所有播放、切歌、暂停功能均由官方接口实现,稳定无广告。

二、JavaScript 交互逻辑(负责所有动态功能)

网易云音乐

获取歌单 ID 方法:

  1. 打开网易云音乐网页版

  2. 打开你的歌单

  3. 看浏览器链接:playlist?id=xxxxxx

  4. 复制 id= 后面的数字,替换进去就行

1. 全局状态变量

统一管理播放器状态,避免功能冲突:

 isDragging:标记是否正在拖动

 isHidden:标记播放器是否处于隐藏状态

 isOverIframe:标记鼠标是否在播放按钮区域

 hideTimer:自动缩回定时器,防止误触

2. 鼠标悬浮自动弹出逻辑

播放器隐藏在屏幕右侧时,鼠标靠近自动弹出,同时清除缩回计时、启用边框拖动,操作极其便捷。

3. 智能自动缩回逻辑(核心优化)

这是最关键的优化点:仅播放器处于屏幕最右侧(99%区域)才会自动缩回,拖到网页中间、左侧永久固定,不会误缩。500ms延迟缩回,避免鼠标快速划过触发误操作。

4. 拖动/点击智能切换

 鼠标悬浮按钮区:关闭拖动,切换为指针状态,正常点击播放、切歌

 鼠标离开按钮区:自动恢复拖动功能,边框任意位置可拖动

5. 自由拖动逻辑

按下鼠标记录坐标,实时跟随鼠标移动,限制拖动范围,不会完全拖出屏幕,拖动结束自动判断是否贴边隐藏。

部署教程

1. 代码放置位置

 Halo博客:后台 → 设置 → 代码注入 → 全局head注入

 WordPress:外观 → 主题编辑器 → 底部footer文件

 静态网页:粘贴在 </body> 标签上方

清空原有代码,粘贴完整源码,保存刷新即可生效。

2. 自定义网易云歌单(更换自己的音乐)

只需修改iframe链接中的歌单ID:

链接示例:id=12937135196

获取ID方法

1. 打开网易云音乐网页版

2. 打开自己的歌单/专辑

3. 复制浏览器链接中 id= 后面的数字

4. 替换源码中的ID即可

自定义修改参数(小白可直接改)

修改参数

作用效果

width:290px / height:92px

调整播放器整体宽高尺寸

bottom:24px / right:24px

调整播放器初始悬浮位置

0.3s

修改弹出/缩回动画速度

500

修改鼠标离开后的缩回延迟时间

windowWidth * 0.99

调整自动隐藏触发灵敏度(数值越小越灵敏)

总结

本播放器可直接部署使用,开发者可根据代码解析自由自定义样式、音源、交互逻辑。支持网易云等其他音源切换,是个人博客、静态网站的最佳悬浮音乐播放器方案!

Peregrine
音乐播放器「每日自动换歌单」2.0