花潮论坛

搜索
热搜: 活动 交友 discuz
楼主: 马黑黑

播放多个本地音频文件的响应式频谱播放器(2.5更新)

[复制链接]
  • TA的每日心情
    开心
    2025-11-17 10:56
  • 签到天数: 1050 天

    [LV.10]以坛为家III

    1881

    主题

    32万

    回帖

    37万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮美女虎龙狗猪多彩人生星月交辉海样胸怀火热情怀优雅迷人神秘浪漫缤纷心情草莓情怀蝴蝶情怀心曲飞扬星星情怀七彩绚丽活泼开朗女儿情怀相遇之美一往情深花好月圆心香一瓣紫色情节飞龙在天金剪刀天籁妙音妙笔生花风雨同行我心永远天长地久幸福快乐绚丽缤纷喜乐安康中秋征文周年庆指尖上的流年舞会之星分析(喊冤)章总结章杀人王小强章最佳杀刺临屏写诗七夕诗钟活动第五届风云第六届风云情人节花潮管理

    发表于 2025-2-2 11:11 | 显示全部楼层

    结果又忍不住去听歌了
     
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-11-30 07:45
  • 签到天数: 1655 天

    [LV.Master]伴坛终老

    3024

    主题

    13万

    回帖

    28万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮帅哥鼠牛虎兔龙蛇马羊猴鸡狗猪多彩人生星月交辉奔放热烈海样胸怀春风拂面火热情怀优雅迷人神秘浪漫相遇之美鹰傲苍穹花好月圆紫色情节飞龙在天王者至尊大将风范音画大师天籁妙音共看流星风雨同行我心永远幸福快乐喜乐安康侠骨柔肠心想事成开朗大方花潮管理

     楼主| 发表于 2025-2-2 12:36 | 显示全部楼层
    红影 发表于 2025-2-2 11:11
    结果又忍不住去听歌了

    听歌有益健康
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-11-30 07:45
  • 签到天数: 1655 天

    [LV.Master]伴坛终老

    3024

    主题

    13万

    回帖

    28万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮帅哥鼠牛虎兔龙蛇马羊猴鸡狗猪多彩人生星月交辉奔放热烈海样胸怀春风拂面火热情怀优雅迷人神秘浪漫相遇之美鹰傲苍穹花好月圆紫色情节飞龙在天王者至尊大将风范音画大师天籁妙音共看流星风雨同行我心永远幸福快乐喜乐安康侠骨柔肠心想事成开朗大方花潮管理

     楼主| 发表于 2025-2-2 12:38 | 显示全部楼层
    花飞飞 发表于 2025-2-2 10:58
    这个好喝。。热腾腾的奶茶来一杯

    热热身子
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-11-30 07:45
  • 签到天数: 1655 天

    [LV.Master]伴坛终老

    3024

    主题

    13万

    回帖

    28万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮帅哥鼠牛虎兔龙蛇马羊猴鸡狗猪多彩人生星月交辉奔放热烈海样胸怀春风拂面火热情怀优雅迷人神秘浪漫相遇之美鹰傲苍穹花好月圆紫色情节飞龙在天王者至尊大将风范音画大师天籁妙音共看流星风雨同行我心永远幸福快乐喜乐安康侠骨柔肠心想事成开朗大方花潮管理

     楼主| 发表于 2025-2-2 12:39 | 显示全部楼层
    花飞飞 发表于 2025-2-2 10:58
    这几天天天用,完全顺手。。
    突然想到卸了的火狐里不知道有没有存一些偏门的网址。。卸快了

    火绒安全的软件管理里面有卸载残余的
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-11-30 07:45
  • 签到天数: 1655 天

    [LV.Master]伴坛终老

    3024

    主题

    13万

    回帖

    28万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮帅哥鼠牛虎兔龙蛇马羊猴鸡狗猪多彩人生星月交辉奔放热烈海样胸怀春风拂面火热情怀优雅迷人神秘浪漫相遇之美鹰傲苍穹花好月圆紫色情节飞龙在天王者至尊大将风范音画大师天籁妙音共看流星风雨同行我心永远幸福快乐喜乐安康侠骨柔肠心想事成开朗大方花潮管理

     楼主| 发表于 2025-2-2 12:39 | 显示全部楼层
    花飞飞 发表于 2025-2-2 10:57
    那敢情好,天荒地老

    白的可能是银子,值钱
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2025-11-17 10:56
  • 签到天数: 1050 天

    [LV.10]以坛为家III

    1881

    主题

    32万

    回帖

    37万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮美女虎龙狗猪多彩人生星月交辉海样胸怀火热情怀优雅迷人神秘浪漫缤纷心情草莓情怀蝴蝶情怀心曲飞扬星星情怀七彩绚丽活泼开朗女儿情怀相遇之美一往情深花好月圆心香一瓣紫色情节飞龙在天金剪刀天籁妙音妙笔生花风雨同行我心永远天长地久幸福快乐绚丽缤纷喜乐安康中秋征文周年庆指尖上的流年舞会之星分析(喊冤)章总结章杀人王小强章最佳杀刺临屏写诗七夕诗钟活动第五届风云第六届风云情人节花潮管理

    发表于 2025-2-2 13:21 | 显示全部楼层

    是啊,尤其喜欢的歌,听了总是那么开心呢
     
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-8-5 16:33
  • 签到天数: 44 天

    [LV.5]常住居民I

    62

    主题

    1万

    回帖

    2万

    积分

    贵宾

    Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7

    花潮美女流光溢彩优雅神秘花潮贵宾

    发表于 2025-2-2 19:01 | 显示全部楼层

    阴天有零星小雨
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-8-5 16:33
  • 签到天数: 44 天

    [LV.5]常住居民I

    62

    主题

    1万

    回帖

    2万

    积分

    贵宾

    Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7

    花潮美女流光溢彩优雅神秘花潮贵宾

    发表于 2025-2-2 19:03 | 显示全部楼层
    马黑黑 发表于 2025-2-2 12:39
    火绒安全的软件管理里面有卸载残余的

    火狐么,没准哪天又装回来了。这个暂时先不清。。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-8-5 16:33
  • 签到天数: 44 天

    [LV.5]常住居民I

    62

    主题

    1万

    回帖

    2万

    积分

    贵宾

    Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7

    花潮美女流光溢彩优雅神秘花潮贵宾

    发表于 2025-2-2 19:04 | 显示全部楼层
    马黑黑 发表于 2025-2-2 12:39
    白的可能是银子,值钱

    看到银子两眼放光,提神
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-11-30 07:45
  • 签到天数: 1655 天

    [LV.Master]伴坛终老

    3024

    主题

    13万

    回帖

    28万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮帅哥鼠牛虎兔龙蛇马羊猴鸡狗猪多彩人生星月交辉奔放热烈海样胸怀春风拂面火热情怀优雅迷人神秘浪漫相遇之美鹰傲苍穹花好月圆紫色情节飞龙在天王者至尊大将风范音画大师天籁妙音共看流星风雨同行我心永远幸福快乐喜乐安康侠骨柔肠心想事成开朗大方花潮管理

     楼主| 发表于 2025-2-2 20:16 | 显示全部楼层
    花飞飞 发表于 2025-2-2 19:04
    看到银子两眼放光,提神

    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-11-30 07:45
  • 签到天数: 1655 天

    [LV.Master]伴坛终老

    3024

    主题

    13万

    回帖

    28万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮帅哥鼠牛虎兔龙蛇马羊猴鸡狗猪多彩人生星月交辉奔放热烈海样胸怀春风拂面火热情怀优雅迷人神秘浪漫相遇之美鹰傲苍穹花好月圆紫色情节飞龙在天王者至尊大将风范音画大师天籁妙音共看流星风雨同行我心永远幸福快乐喜乐安康侠骨柔肠心想事成开朗大方花潮管理

     楼主| 发表于 2025-2-2 20:18 | 显示全部楼层

    雨伞俺有的
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-8-5 16:33
  • 签到天数: 44 天

    [LV.5]常住居民I

    62

    主题

    1万

    回帖

    2万

    积分

    贵宾

    Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7

    花潮美女流光溢彩优雅神秘花潮贵宾

    发表于 2025-2-2 20:45 | 显示全部楼层
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-8-5 16:33
  • 签到天数: 44 天

    [LV.5]常住居民I

    62

    主题

    1万

    回帖

    2万

    积分

    贵宾

    Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7

    花潮美女流光溢彩优雅神秘花潮贵宾

    发表于 2025-2-2 20:45 | 显示全部楼层

    毛毛雨。。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-11-30 07:45
  • 签到天数: 1655 天

    [LV.Master]伴坛终老

    3024

    主题

    13万

    回帖

    28万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮帅哥鼠牛虎兔龙蛇马羊猴鸡狗猪多彩人生星月交辉奔放热烈海样胸怀春风拂面火热情怀优雅迷人神秘浪漫相遇之美鹰傲苍穹花好月圆紫色情节飞龙在天王者至尊大将风范音画大师天籁妙音共看流星风雨同行我心永远幸福快乐喜乐安康侠骨柔肠心想事成开朗大方花潮管理

     楼主| 发表于 2025-2-2 22:06 | 显示全部楼层

    毛毛雨也是雨
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-11-30 07:45
  • 签到天数: 1655 天

    [LV.Master]伴坛终老

    3024

    主题

    13万

    回帖

    28万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮帅哥鼠牛虎兔龙蛇马羊猴鸡狗猪多彩人生星月交辉奔放热烈海样胸怀春风拂面火热情怀优雅迷人神秘浪漫相遇之美鹰傲苍穹花好月圆紫色情节飞龙在天王者至尊大将风范音画大师天籁妙音共看流星风雨同行我心永远幸福快乐喜乐安康侠骨柔肠心想事成开朗大方花潮管理

     楼主| 发表于 2025-2-2 22:06 | 显示全部楼层

    那不错
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-11-30 07:45
  • 签到天数: 1655 天

    [LV.Master]伴坛终老

    3024

    主题

    13万

    回帖

    28万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮帅哥鼠牛虎兔龙蛇马羊猴鸡狗猪多彩人生星月交辉奔放热烈海样胸怀春风拂面火热情怀优雅迷人神秘浪漫相遇之美鹰傲苍穹花好月圆紫色情节飞龙在天王者至尊大将风范音画大师天籁妙音共看流星风雨同行我心永远幸福快乐喜乐安康侠骨柔肠心想事成开朗大方花潮管理

     楼主| 发表于 2025-2-4 08:51 | 显示全部楼层
    2月4日更新:


    (一)鼠标指针移动到背景图片地址栏自动获焦并选中地址(若有);
    (二)音乐列表:
            一是设置一定透明度,鼠标指针移动到其上时恢复不透明度为0即没有透明度;
            二是滚动条自动隐藏,仅在鼠标指针经过其上时出现(若有)。

    完整代码:
    1. <style>
    2. /* 父元素 */
    3. #papa {
    4.         margin: 30px auto 0;
    5.         padding: 10px;
    6.         width: 800px;
    7.         height: 400px;
    8.         font-size: 16px;
    9.         background: linear-gradient(to bottom right, #000, #ffc);
    10.         box-shadow: 3px 6px 20px #000;
    11.         border-radius: 6px;
    12.         display: grid;
    13.         place-items: center;
    14.         position: relative;
    15. }

    16. /* 选择本地音乐父元素 */
    17. #openFile {
    18.         position: absolute;
    19.         left: 15px;
    20.         top: 15px;
    21.         width: calc(100% - 30px);
    22. }

    23. /* 选择音乐控件 */
    24. #mfile { display: none; }

    25. /* 选择音乐按钮 */
    26. #selectSong {
    27.         margin-right: 8px;
    28.         border: 2px solid #ccc;
    29.         border-radius: 6px;
    30.         outline: none;
    31.         background: none;
    32.         color: snow;
    33.         cursor: pointer;
    34. }

    35. /* 背景图片地址栏 */
    36. #bgurl {
    37.         position: absolute;
    38.         right: 0;
    39.         display: none;
    40. }


    41. #openFile:hover #bgurl {
    42.         display: inline;
    43. }

    44. /* 选择音乐按钮指针经过 */
    45. #selectSong:hover { background: darkred; }

    46. /* 当前播放曲目 */
    47. #curSong { color: #eee; }

    48. /* 播放器 */
    49. #mplayer {
    50.         --bg1: teal;
    51.         --bg2: snow;
    52.         --ppLen: 4px;
    53.         --prog: white;
    54.         --track: silver;
    55.         --prg: 0%;
    56.         --ppCap: white;
    57.         position: absolute;
    58.         right: 180px;
    59.         width: 100px;
    60.         height: 100px;
    61.         border-radius: 50%;
    62.         background: linear-gradient(
    63.                 to right,
    64.                 var(--prog) var(--prg),
    65.                 var(--track) var(--prg),
    66.                 var(--track) 0
    67.         ) no-repeat 0 50% / 100% 2px;
    68.         cursor: pointer;
    69.         display: grid;
    70.         place-items: center;
    71. }

    72. /* 播放器指针经过 */
    73. #mplayer:hover {
    74.         filter: hue-rotate(90deg) drop-shadow(0 0 26px black);
    75. }

    76. /* 播放器伪元素 :音频时间信息 */
    77. #mplayer::before, #mplayer::after {
    78.         position: absolute;
    79.         color: snow;
    80. }

    81. /* 播放器伪元素一 :当前播放时间 */
    82. #mplayer::before {
    83.         content: attr(data-cu);
    84.         top: 20%;
    85. }

    86. /* 播放器伪元素二 :音频时长 */
    87. #mplayer::after {
    88.         content: attr(data-du);
    89.         top: 56%;
    90. }

    91. /* 频谱条 */
    92. .pp {
    93.         position: absolute;
    94.         left: calc(50% - 2px);
    95.         bottom: 50%;
    96.         width: var(--ppLen);
    97.         height: 20px;
    98.         background: linear-gradient(to top, var(--bg1), var(--bg2));
    99.         transform-origin: 50% 100%;
    100.         transform: rotate(var(--deg)) translate(-50px, 0);
    101.         display: grid;
    102.         place-items: center;
    103. }

    104. /* 频谱条伪元素 :频谱帽 */
    105. .pp::after {
    106.         position: absolute;
    107.         content: '';
    108.         width: calc(var(--ppLen) + 4px);
    109.         height: calc(var(--ppLen) + 4px);
    110.         top: 0px;
    111.         background: var(--bg2);
    112.         border-radius: 50%;
    113. }

    114. /* 音乐列表 */
    115. #mlist {
    116.         position: absolute;
    117.         left: 20px;
    118.         top: 60px;
    119.         min-width: 40%;
    120.         max-width: 50%;
    121.         min-height: 20%;
    122.         max-height: calc(100% - 80px);
    123.         color: silver;
    124.         font-size: 14px;
    125.         line-height: 20px;
    126.         overflow: hidden;
    127.         opacity: .4;
    128. }

    129. /* 音乐列表鼠标经过 */
    130. #mlist:hover {
    131.         overflow: auto;
    132.         opacity: 1;
    133. }

    134. /* 音乐列表项目一 :待播放曲目 */
    135. .list1 { cursor: pointer; }

    136. /* 音乐列表项目二 :正在播放曲目 */
    137. .list2 {
    138.         color: cyan;
    139.         cursor:default;
    140. }

    141. /* 音乐列表项目一指针经过 */
    142. .list1:hover { color: white; }
    143. </style>

    144. <div id="papa">
    145.         <div id="openFile">
    146.                 <input id="selectSong" type="button" value="选择音乐" />
    147.                 <input type="file" id="mfile" accept=".mp3,.ogg,.wav,.acc,.webm,.flac" multiple />
    148.                 <span id="curSong"></span>
    149.                 <input id="bgurl" type="text" placeholder="背景 : 网络图片地址" value="" />
    150.         </div>
    151.         <div id="mplayer" class="mplayer"></div>
    152.         <div id="mlist"></div>
    153.         <audio id="aud"></audio>
    154. </div>
    155. <p style="text-align:right"><br>更新 :2025年2月4日 &nbsp;&nbsp;&nbsp;<br></p>

    156. <script>

    157. //选择的文件, 播放列表, 波形数据, 频谱
    158. let files=[], playAr = [], output = [], pps = [];
    159. //打开文件次数, 频谱条总数
    160. let openIdx = 0, total = 30;

    161. //获取波形数据
    162. const getDatas = () => {
    163.         if(openIdx > 0) return;
    164.         openIdx ++;
    165.         Ac = new AudioContext;
    166.         source = Ac.createMediaElementSource(aud);
    167.         analyser = Ac.createAnalyser();
    168.         source.connect(analyser);
    169.         analyser.connect(Ac.destination);
    170.         output = new Uint8Array(total);
    171. };

    172. //生成频谱条
    173. Array(total).fill(0).forEach((_, k) => {
    174.         let pp = document.createElement('span');
    175.         pp.className = 'pp';
    176.         pp.style.cssText += `--deg: ${360 / total * k}deg`;
    177.         mplayer.appendChild(pp);
    178.         pps.push(pp);
    179. });

    180. //波形数据刷新
    181. (function update() {
    182.         if(aud.src) analyser.getByteFrequencyData(output);
    183.         for(let j = 0; j < total ; j++) {
    184.                 pps[j].style.height = output[j] / 2 + 'px';
    185.         }
    186.         window.requestAnimationFrame(update);
    187. })();

    188. //播放 :idx为空时随机播放
    189. const mplay = (idx = null) => {
    190.         if(files.length === 0) return;
    191.         let isScrolling = false;
    192.         if(idx === null) {
    193.                 if(playAr.length === 0) playAr = ranNum(files.length);
    194.                 let tmpIdx = Math.floor(Math.random() * playAr.length);
    195.                 idx = playAr[tmpIdx];
    196.                 playAr.splice(tmpIdx, 1);
    197.                 isScrolling = true;
    198.         }
    199.         aud.src = URL.createObjectURL(files[idx]);
    200.         let name = files[idx].name;
    201.         curSong.innerText = name.substring(0, name.lastIndexOf('.')) + `(${files.length}/${idx+1})`;
    202.         aud.play();
    203.         mlist.innerHTML = showList(files, idx);
    204.         if(isScrolling) mlist.scrollTop = 20 * idx; //scrolling(20, idx);
    205. };

    206. //显示音乐列表
    207. const showList = (ar, idx) => {
    208.         let res = '';
    209.         for(let j = 0; j < ar.length; j ++) {
    210.                 let item = (j + 1) + '. ';
    211.                 item += j === idx ?
    212.                         `<span class="list2">${ar[j].name}</span>` :
    213.                         `<span class="list1" onclick="mplay(${j})">${ar[j].name}</span>`;
    214.                 res += item + '<br>';
    215.         }
    216.         return res;
    217. };

    218. //生成不重复随机数组
    219. const ranNum = (total) => {
    220.         let ar = Array(total).fill().map((_,key) => key);
    221.         ar.sort(() => 0.5 - Math.random());
    222.         return ar;
    223. };

    224. //秒转分
    225. const s2m = (seconds) => {
    226.         if (!seconds) return '00:00';
    227.         let min = parseInt(seconds / 60), sec = parseFloat(Math.floor(seconds) % 60);
    228.         if(min < 10) min = '0' + min;
    229.         if(sec < 10) sec = '0' + sec;
    230.         return min + ':' + sec;
    231. };

    232. //判断进度条区域
    233. const innerH = (e, h) => e.offsetY > h / 2 - 5 && e.offsetY < h / 2 + 5;

    234. //audio timeupdate监听事件
    235. aud.addEventListener('timeupdate', () => {
    236.         mplayer.style.setProperty('--prg', aud.currentTime / aud.duration * 100 + '%');
    237.         mplayer.dataset.cu = s2m(aud.currentTime);
    238.         mplayer.dataset.du = s2m(aud.duration);
    239. });

    240. //单曲播放结束
    241. aud.addEventListener('ended',() => mplay());

    242. //选择歌曲
    243. selectSong.onclick = () => mfile.click();

    244. //文件选择器改变
    245. mfile.onchange = () => {
    246.         let filelist = mfile.files;
    247.         if(filelist.length === 0) return;
    248.         files.length = 0;
    249.         for(let j = 0; j < filelist.length; j ++) {
    250.                 files.push(filelist[j]);
    251.         }
    252.         playAr = ranNum(files.length);
    253.         mplay();
    254.         getDatas();
    255. }

    256. //播放器点击
    257. mplayer.onclick = (e) => {
    258.         if(files.length < 1) return;
    259.         if(innerH(e,mplayer.clientHeight)) {
    260.                 aud.currentTime = aud.duration * e.offsetX / mplayer.offsetWidth;
    261.         }else{
    262.                 aud.paused ? aud.play() : aud.pause();
    263.         }
    264. };

    265. //播放器鼠标移过
    266. mplayer.onmousemove = (e) => {
    267.         mplayer.title = innerH(e,mplayer.clientHeight) ?
    268.                 s2m(aud.duration * e.offsetX / mplayer.offsetWidth) :
    269.                 (aud.paused ? '点击播放' : '点击暂停');
    270. };

    271. //背景图地址栏输入事件
    272. bgurl.oninput = () => {
    273.         let img = new Image(), src = bgurl.value.trim();
    274.         img.src = src;
    275.         img.onload = () => {
    276.                 papa.style.cssText += `background: url(${src}) no-repeat center/cover;`;
    277.                 localStorage.setItem('player_url', src)
    278.         };
    279. };

    280. //背景图地址栏鼠标经过事件
    281. bgurl.onmouseover = () => {
    282.         bgurl.focus();
    283.         bgurl.setSelectionRange(0,bgurl.value.length);
    284. };

    285. //加载背景图
    286. const player_url = bgurl.value = localStorage.getItem('player_url');
    287. if(player_url) papa.style.cssText += `background: url(${player_url}) no-repeat center/cover;`;

    288. </script>
    复制代码


    评分

    参与人数 1威望 +30 金钱 +60 经验 +30 收起 理由
    花飞飞 + 30 + 60 + 30 很给力!

    查看全部评分

    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-11-30 07:45
  • 签到天数: 1655 天

    [LV.Master]伴坛终老

    3024

    主题

    13万

    回帖

    28万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮帅哥鼠牛虎兔龙蛇马羊猴鸡狗猪多彩人生星月交辉奔放热烈海样胸怀春风拂面火热情怀优雅迷人神秘浪漫相遇之美鹰傲苍穹花好月圆紫色情节飞龙在天王者至尊大将风范音画大师天籁妙音共看流星风雨同行我心永远幸福快乐喜乐安康侠骨柔肠心想事成开朗大方花潮管理

     楼主| 发表于 2025-2-5 10:35 | 显示全部楼层
    本帖最后由 马黑黑 于 2025-2-5 12:17 编辑

    2月5日更新内容:改进音乐列表滚动条样式(支持chrome和Firefox)

    1. <style>
    2. /* 父元素 */
    3. #papa {
    4.         margin: 30px auto 0;
    5.         padding: 10px;
    6.         width: 800px;
    7.         height: 400px;
    8.         font-size: 16px;
    9.         background: linear-gradient(to bottom right, #000, #ffc);
    10.         box-shadow: 3px 6px 20px #000;
    11.         border-radius: 6px;
    12.         display: grid;
    13.         place-items: center;
    14.         position: relative;
    15. }

    16. /* 选择本地音乐父元素 */
    17. #openFile {
    18.         position: absolute;
    19.         left: 15px;
    20.         top: 15px;
    21.         width: calc(100% - 30px);
    22. }

    23. /* 选择音乐控件 */
    24. #mfile { display: none; }

    25. /* 选择音乐按钮 */
    26. #selectSong {
    27.         margin-right: 8px;
    28.         border: 2px solid #ccc;
    29.         border-radius: 6px;
    30.         outline: none;
    31.         background: none;
    32.         color: snow;
    33.         cursor: pointer;
    34. }

    35. /* 背景图片地址栏 */
    36. #bgurl {
    37.         position: absolute;
    38.         right: 0;
    39.         display: none;
    40. }


    41. #openFile:hover #bgurl {
    42.         display: inline;
    43. }

    44. /* 选择音乐按钮指针经过 */
    45. #selectSong:hover { background: darkred; }

    46. /* 当前播放曲目 */
    47. #curSong { color: #eee; }

    48. /* 播放器 */
    49. #mplayer {
    50.         --bg1: teal;
    51.         --bg2: snow;
    52.         --ppLen: 4px;
    53.         --prog: white;
    54.         --track: silver;
    55.         --prg: 0%;
    56.         --ppCap: white;
    57.         position: absolute;
    58.         right: 180px;
    59.         width: 100px;
    60.         height: 100px;
    61.         border-radius: 50%;
    62.         background: linear-gradient(
    63.                 to right,
    64.                 var(--prog) var(--prg),
    65.                 var(--track) var(--prg),
    66.                 var(--track) 0
    67.         ) no-repeat 0 50% / 100% 2px;
    68.         cursor: pointer;
    69.         display: grid;
    70.         place-items: center;
    71. }

    72. /* 播放器指针经过 */
    73. #mplayer:hover {
    74.         filter: hue-rotate(90deg) drop-shadow(0 0 26px black);
    75. }

    76. /* 播放器伪元素 :音频时间信息 */
    77. #mplayer::before, #mplayer::after {
    78.         position: absolute;
    79.         color: snow;
    80. }

    81. /* 播放器伪元素一 :当前播放时间 */
    82. #mplayer::before {
    83.         content: attr(data-cu);
    84.         top: 20%;
    85. }

    86. /* 播放器伪元素二 :音频时长 */
    87. #mplayer::after {
    88.         content: attr(data-du);
    89.         top: 56%;
    90. }

    91. /* 频谱条 */
    92. .pp {
    93.         position: absolute;
    94.         left: calc(50% - 2px);
    95.         bottom: 50%;
    96.         width: var(--ppLen);
    97.         height: 20px;
    98.         background: linear-gradient(to top, var(--bg1), var(--bg2));
    99.         transform-origin: 50% 100%;
    100.         transform: rotate(var(--deg)) translate(-50px, 0);
    101.         display: grid;
    102.         place-items: center;
    103. }

    104. /* 频谱条伪元素 :频谱帽 */
    105. .pp::after {
    106.         position: absolute;
    107.         content: '';
    108.         width: calc(var(--ppLen) + 4px);
    109.         height: calc(var(--ppLen) + 4px);
    110.         top: 0px;
    111.         background: var(--bg2);
    112.         border-radius: 50%;
    113. }

    114. /* 音乐列表 */
    115. #mlist {
    116.         position: absolute;
    117.         left: 20px;
    118.         top: 60px;
    119.         min-width: 40%;
    120.         max-width: 50%;
    121.         min-height: 20%;
    122.         max-height: calc(100% - 80px);
    123.         color: silver;
    124.         font-size: 14px;
    125.         line-height: 20px;
    126.         opacity: .4;
    127.         /* 滚动条 */
    128.         overflow: hidden;
    129.         scrollbar-width: thin;
    130.         scrollbar-color: teal rgba(255,255,255,.2);
    131. }

    132. /* 音乐列表鼠标经过 */
    133. #mlist:hover {
    134.         overflow: auto;
    135.         opacity: 1;
    136. }

    137. /* 音乐列表项目一 :待播放曲目 */
    138. .list1 { cursor: pointer; }

    139. /* 音乐列表项目二 :正在播放曲目 */
    140. .list2 {
    141.         color: cyan;
    142.         cursor:default;
    143. }

    144. /* 音乐列表项目一指针经过 */
    145. .list1:hover { color: white; }
    146. </style>

    147. <div id="papa">
    148.         <div id="openFile">
    149.                 <input id="selectSong" type="button" value="选择音乐" />
    150.                 <input type="file" id="mfile" accept=".mp3,.ogg,.wav,.acc,.webm,.flac" multiple />
    151.                 <span id="curSong"></span>
    152.                 <input id="bgurl" type="text" placeholder="背景 : 网络图片地址" value="" />
    153.         </div>
    154.         <div id="mplayer" class="mplayer"></div>
    155.         <div id="mlist"></div>
    156.         <audio id="aud"></audio>
    157. </div>
    158. <p style="text-align:right"><br>更新 :2025年2月5日 &nbsp;&nbsp;&nbsp;<br></p>

    159. <script>

    160. //选择的文件, 播放列表, 波形数据, 频谱
    161. let files=[], playAr = [], output = [], pps = [];
    162. //打开文件次数, 频谱条总数
    163. let openIdx = 0, total = 30;

    164. //获取波形数据
    165. const getDatas = () => {
    166.         if(openIdx > 0) return;
    167.         openIdx ++;
    168.         Ac = new AudioContext;
    169.         source = Ac.createMediaElementSource(aud);
    170.         analyser = Ac.createAnalyser();
    171.         source.connect(analyser);
    172.         analyser.connect(Ac.destination);
    173.         output = new Uint8Array(total);
    174. };

    175. //生成频谱条
    176. Array(total).fill(0).forEach((_, k) => {
    177.         let pp = document.createElement('span');
    178.         pp.className = 'pp';
    179.         pp.style.cssText += `--deg: ${360 / total * k}deg`;
    180.         mplayer.appendChild(pp);
    181.         pps.push(pp);
    182. });

    183. //波形数据刷新
    184. (function update() {
    185.         if(aud.src) analyser.getByteFrequencyData(output);
    186.         for(let j = 0; j < total ; j++) {
    187.                 pps[j].style.height = output[j] / 2 + 'px';
    188.         }
    189.         window.requestAnimationFrame(update);
    190. })();

    191. //播放 :idx为空时随机播放
    192. const mplay = (idx = null) => {
    193.         if(files.length === 0) return;
    194.         let isScrolling = false;
    195.         if(idx === null) {
    196.                 if(playAr.length === 0) playAr = ranNum(files.length);
    197.                 let tmpIdx = Math.floor(Math.random() * playAr.length);
    198.                 idx = playAr[tmpIdx];
    199.                 playAr.splice(tmpIdx, 1);
    200.                 isScrolling = true;
    201.         }
    202.         aud.src = URL.createObjectURL(files[idx]);
    203.         let name = files[idx].name;
    204.         curSong.innerText = name.substring(0, name.lastIndexOf('.')) + `(${files.length}/${idx+1})`;
    205.         aud.play();
    206.         mlist.innerHTML = showList(files, idx);
    207.         if(isScrolling) mlist.scrollTop = 20 * idx; //scrolling(20, idx);
    208. };

    209. //显示音乐列表
    210. const showList = (ar, idx) => {
    211.         let res = '';
    212.         for(let j = 0; j < ar.length; j ++) {
    213.                 let item = (j + 1) + '. ';
    214.                 item += j === idx ?
    215.                         `<span class="list2">${ar[j].name}</span>` :
    216.                         `<span class="list1" onclick="mplay(${j})">${ar[j].name}</span>`;
    217.                 res += item + '<br>';
    218.         }
    219.         return res;
    220. };

    221. //生成不重复随机数组
    222. const ranNum = (total) => {
    223.         let ar = Array(total).fill().map((_,key) => key);
    224.         ar.sort(() => 0.5 - Math.random());
    225.         return ar;
    226. };

    227. //秒转分
    228. const s2m = (seconds) => {
    229.         if (!seconds) return '00:00';
    230.         let min = parseInt(seconds / 60), sec = parseFloat(Math.floor(seconds) % 60);
    231.         if(min < 10) min = '0' + min;
    232.         if(sec < 10) sec = '0' + sec;
    233.         return min + ':' + sec;
    234. };

    235. //判断进度条区域
    236. const innerH = (e, h) => e.offsetY > h / 2 - 5 && e.offsetY < h / 2 + 5;

    237. //audio timeupdate监听事件
    238. aud.addEventListener('timeupdate', () => {
    239.         mplayer.style.setProperty('--prg', aud.currentTime / aud.duration * 100 + '%');
    240.         mplayer.dataset.cu = s2m(aud.currentTime);
    241.         mplayer.dataset.du = s2m(aud.duration);
    242. });

    243. //单曲播放结束
    244. aud.addEventListener('ended',() => mplay());

    245. //选择歌曲
    246. selectSong.onclick = () => mfile.click();

    247. //文件选择器改变
    248. mfile.onchange = () => {
    249.         let filelist = mfile.files;
    250.         if(filelist.length === 0) return;
    251.         files.length = 0;
    252.         for(let j = 0; j < filelist.length; j ++) {
    253.                 files.push(filelist[j]);
    254.         }
    255.         playAr = ranNum(files.length);
    256.         mplay();
    257.         getDatas();
    258. }

    259. //播放器点击
    260. mplayer.onclick = (e) => {
    261.         if(files.length < 1) return;
    262.         if(innerH(e,mplayer.clientHeight)) {
    263.                 aud.currentTime = aud.duration * e.offsetX / mplayer.offsetWidth;
    264.         }else{
    265.                 aud.paused ? aud.play() : aud.pause();
    266.         }
    267. };

    268. //播放器鼠标移过
    269. mplayer.onmousemove = (e) => {
    270.         mplayer.title = innerH(e,mplayer.clientHeight) ?
    271.                 s2m(aud.duration * e.offsetX / mplayer.offsetWidth) :
    272.                 (aud.paused ? '点击播放' : '点击暂停');
    273. };

    274. //背景图地址栏输入事件
    275. bgurl.oninput = () => {
    276.         let img = new Image(), src = bgurl.value.trim();
    277.         img.src = src;
    278.         img.onload = () => {
    279.                 papa.style.cssText += `background: url(${src}) no-repeat center/cover;`;
    280.                 localStorage.setItem('player_url', src)
    281.         };
    282. };

    283. //背景图地址栏鼠标经过事件
    284. bgurl.onmouseover = () => {
    285.         bgurl.focus();
    286.         bgurl.setSelectionRange(0,bgurl.value.length);
    287. };

    288. //加载背景图
    289. const player_url = bgurl.value = localStorage.getItem('player_url');
    290. if(player_url) papa.style.cssText += `background: url(${player_url}) no-repeat center/cover;`;

    291. </script>
    复制代码


    评分

    参与人数 1威望 +30 金钱 +60 经验 +30 收起 理由
    花飞飞 + 30 + 60 + 30 很给力!

    查看全部评分

    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-11-30 07:45
  • 签到天数: 1655 天

    [LV.Master]伴坛终老

    3024

    主题

    13万

    回帖

    28万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9Rank: 9

    花潮帅哥鼠牛虎兔龙蛇马羊猴鸡狗猪多彩人生星月交辉奔放热烈海样胸怀春风拂面火热情怀优雅迷人神秘浪漫相遇之美鹰傲苍穹花好月圆紫色情节飞龙在天王者至尊大将风范音画大师天籁妙音共看流星风雨同行我心永远幸福快乐喜乐安康侠骨柔肠心想事成开朗大方花潮管理

     楼主| 发表于 2025-2-5 10:38 | 显示全部楼层
    这个图片做做背景不错:


                                   
    登录/注册后可看大图

    评分

    参与人数 1威望 +30 金钱 +60 经验 +30 收起 理由
    花飞飞 + 30 + 60 + 30 很给力!

    查看全部评分

    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-8-5 16:33
  • 签到天数: 44 天

    [LV.5]常住居民I

    62

    主题

    1万

    回帖

    2万

    积分

    贵宾

    Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7

    花潮美女流光溢彩优雅神秘花潮贵宾

    发表于 2025-2-5 13:10 | 显示全部楼层

    事实证明今年是个暖冬,几乎没冷过
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2025-8-5 16:33
  • 签到天数: 44 天

    [LV.5]常住居民I

    62

    主题

    1万

    回帖

    2万

    积分

    贵宾

    Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7Rank: 7

    花潮美女流光溢彩优雅神秘花潮贵宾

    发表于 2025-2-5 13:12 | 显示全部楼层

    一杯解万愁
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|手机版|Archiver|服务支持:DZ动力|huachaowang.com Inc. ( 蜀ICP备17032287号-1 )

    GMT+8, 2025-11-30 16:49 , Processed in 0.098666 second(s), 29 queries .

    Powered by Discuz! X3.4

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表