马黑黑 发表于 2025-3-18 14:02

卡路里

<style>
    @import 'https://638183.freep.cn/638183/web/ku/dbplayer.css';
    #tz { margin: 30px 0 30px calc(50% - 721px); width: 1280px; height: 720px; background: url('https://638183.freep.cn/638183/t24/5/calorie.jpg') no-repeat center/cover; }
</style>

<div id="tz" class="pa">
    <audio id="audio" src="https://music.163.com/song/media/outer/url?id=1294924781" autoplay loop></audio>
    <video class="vid" src="https://bpic.588ku.com/video_listen/588ku_video/23/09/15/19/59/41/video6504472dc0023.mp4" loop muted></video>
</div>

<script type="module">
import { dbplay } from 'https://638183.freep.cn/638183/web/ku/dbplayer.js';

var lrc = `
孟美岐:\n每天起床第一句 先给自己打个气\n吴宣仪:\n每次多吃一粒米 都要说声对不起\n段奥娟:\n魔镜魔镜看看我 我的锁骨在哪里\n紫宁:\n美丽 我要美丽 我要变成万人迷\n合:\nPose pose\n我要变成万人迷\nPose pose\n徐梦洁:\n为了变成小蛮腰 天天提着一口气\n赖美云:\n为了穿上比基尼 吃草吃成沙拉精\n傅菁:\n天生丽质难自弃 可惜吃啥我都不腻\n合:\n努力 我要努力 我要变成万人迷\n李紫婷/赖美云/紫宁/徐梦洁:\nWow\n吴宣仪/孟美岐/段奥娟/傅菁:\n卡路里卡路里卡路\n卡路里卡路里卡路\n卡路里卡路里卡路\n卡路里卡路里卡路\n合:\n卡路里我的天敌\n杨超越:\n燃烧我的卡路里\n合:\n拜拜 甜甜圈 珍珠奶茶方便面\n火锅米饭大盘鸡\n孟美岐/吴宣仪:\n拿走拿走别客气\n合:\n拜拜 咖啡因 戒掉可乐戒油腻\n沙发外卖玩游戏\nYamy/Sunnee:\n别再熬夜伤身体\n合:\n来来 后转体 高温瑜伽仰卧起\n动感单车普拉提\n赖美云/徐梦洁:\n保温杯里泡枸杞\n合:\n来来 深呼吸 晨跑夜跑游几米\n平板哑铃划船机 不达目的不放弃\n吴宣仪:\n为了变成小蛮腰 天天提着一口气\n孟美岐:\n为了穿上比基尼 吃草吃成沙拉精\n李紫婷:\n天生丽质难自弃 可惜吃啥我都不腻\n合:\n努力 我要努力 我要变成万人迷\n李紫婷/赖美云/紫宁/徐梦洁:\nWow\n吴宣仪/孟美岐/段奥娟/傅菁:\n卡路里卡路里卡路\n卡路里卡路里卡路\n卡路里卡路里卡路\n卡路里卡路里卡路\n合:\n卡路里我的天敌\n杨超越:\n燃烧我的卡路里\n合:\n拜拜 甜甜圈 珍珠奶茶方便面\n火锅米饭大盘鸡 拿走拿走别客气\n拜拜 咖啡因 戒掉可乐戒油腻\n沙发外卖玩游戏 别再熬夜伤身体\n来来 后转体 高温瑜伽仰卧起\n动感单车普拉提 保温杯里泡枸杞\n来来 深呼吸 晨跑夜跑游几米\n平板哑铃划船机 不达目的不放弃\nYamy/Sunnee(Rap):\nYamy:\n奇了怪了 小的时候明明是 妈妈说\n吃光盘中餐粒粒 皆辛苦\nSunnee:\n直到最爱的裙子的扣子都系不上了\nYamy:\n原来吃得掉 甩不掉 更辛苦\nYamy:\n希望 体重 秤是坏的\nSunnee:\n帅哥 爱唐代的\n合:\n不如跟着节奏没在怕的 努努力\n别让卡路里卡路里 卡住你\n不达目的不放弃\n杨超越:\n燃烧我的卡路里\n合:\n拜拜 甜甜圈 珍珠奶茶方便面\n火锅米饭大盘鸡 拿走拿走别客气\n拜拜 咖啡因 戒掉可乐戒油腻\n沙发外卖玩游戏 别再熬夜伤身体\n来来 后转体 高温瑜伽仰卧起\n动感单车普拉提 保温杯里泡枸杞\n来来 深呼吸 晨跑夜跑游几米\n平板哑铃划船机 不达目的不放弃\n不放弃\n燃烧我的卡路里\n不放弃\n燃烧我的卡路里\n我要变成万人迷\n-- End --
`;

dbplay(tz,lrc);
</script>

马黑黑 发表于 2025-3-18 14:03

<div id="hEdiv"><pre id="hEpre">
&lt;style&gt;
    @import 'https://638183.freep.cn/638183/web/ku/dbplayer.css';
    #tz { margin: 30px 0 30px calc(50% - 721px); width: 1280px; height: 720px; background: url('https://638183.freep.cn/638183/t24/5/calorie.jpg') no-repeat center/cover; }
&lt;/style&gt;

&lt;div id="tz" class="pa"&gt;
    &lt;audio id="audio" src="https://music.163.com/song/media/outer/url?id=1294924781" autoplay loop&gt;&lt;/audio&gt;
    &lt;video class="vid" src="https://bpic.588ku.com/video_listen/588ku_video/23/09/15/19/59/41/video6504472dc0023.mp4" loop muted&gt;&lt;/video&gt;
&lt;/div&gt;

&lt;script type="module"&gt;
import { dbplay } from 'https://638183.freep.cn/638183/web/ku/dbplayer.js';

var lrc = `
孟美岐:\n每天起床第一句 先给自己打个气\n吴宣仪:\n每次多吃一粒米 都要说声对不起\n段奥娟:\n魔镜魔镜看看我 我的锁骨在哪里\n紫宁:\n美丽 我要美丽 我要变成万人迷\n合:\nPose pose\n我要变成万人迷\nPose pose\n徐梦洁:\n为了变成小蛮腰 天天提着一口气\n赖美云:\n为了穿上比基尼 吃草吃成沙拉精\n傅菁:\n天生丽质难自弃 可惜吃啥我都不腻\n合:\n努力 我要努力 我要变成万人迷\n李紫婷/赖美云/紫宁/徐梦洁:\nWow\n吴宣仪/孟美岐/段奥娟/傅菁:\n卡路里卡路里卡路\n卡路里卡路里卡路\n卡路里卡路里卡路\n卡路里卡路里卡路\n合:\n卡路里我的天敌\n杨超越:\n燃烧我的卡路里\n合:\n拜拜 甜甜圈 珍珠奶茶方便面\n火锅米饭大盘鸡\n孟美岐/吴宣仪:\n拿走拿走别客气\n合:\n拜拜 咖啡因 戒掉可乐戒油腻\n沙发外卖玩游戏\nYamy/Sunnee:\n别再熬夜伤身体\n合:\n来来 后转体 高温瑜伽仰卧起\n动感单车普拉提\n赖美云/徐梦洁:\n保温杯里泡枸杞\n合:\n来来 深呼吸 晨跑夜跑游几米\n平板哑铃划船机 不达目的不放弃\n吴宣仪:\n为了变成小蛮腰 天天提着一口气\n孟美岐:\n为了穿上比基尼 吃草吃成沙拉精\n李紫婷:\n天生丽质难自弃 可惜吃啥我都不腻\n合:\n努力 我要努力 我要变成万人迷\n李紫婷/赖美云/紫宁/徐梦洁:\nWow\n吴宣仪/孟美岐/段奥娟/傅菁:\n卡路里卡路里卡路\n卡路里卡路里卡路\n卡路里卡路里卡路\n卡路里卡路里卡路\n合:\n卡路里我的天敌\n杨超越:\n燃烧我的卡路里\n合:\n拜拜 甜甜圈 珍珠奶茶方便面\n火锅米饭大盘鸡 拿走拿走别客气\n拜拜 咖啡因 戒掉可乐戒油腻\n沙发外卖玩游戏 别再熬夜伤身体\n来来 后转体 高温瑜伽仰卧起\n动感单车普拉提 保温杯里泡枸杞\n来来 深呼吸 晨跑夜跑游几米\n平板哑铃划船机 不达目的不放弃\nYamy/Sunnee(Rap):\nYamy:\n奇了怪了 小的时候明明是 妈妈说\n吃光盘中餐粒粒 皆辛苦\nSunnee:\n直到最爱的裙子的扣子都系不上了\nYamy:\n原来吃得掉 甩不掉 更辛苦\nYamy:\n希望 体重 秤是坏的\nSunnee:\n帅哥 爱唐代的\n合:\n不如跟着节奏没在怕的 努努力\n别让卡路里卡路里 卡住你\n不达目的不放弃\n杨超越:\n燃烧我的卡路里\n合:\n拜拜 甜甜圈 珍珠奶茶方便面\n火锅米饭大盘鸡 拿走拿走别客气\n拜拜 咖啡因 戒掉可乐戒油腻\n沙发外卖玩游戏 别再熬夜伤身体\n来来 后转体 高温瑜伽仰卧起\n动感单车普拉提 保温杯里泡枸杞\n来来 深呼吸 晨跑夜跑游几米\n平板哑铃划船机 不达目的不放弃\n不放弃\n燃烧我的卡路里\n不放弃\n燃烧我的卡路里\n我要变成万人迷\n-- End --
`;

dbplay(tz,lrc);
&lt;/script&gt;
</pre></div>

<script type="module">
import hlight from 'https://638183.freep.cn/638183/web/helight/helight1.js';
hlight.hl(hEdiv, hEpre);
</script>

马黑黑 发表于 2025-3-18 14:16

这是改装过的豆包生成的“炫酷音频播放器”。我会在下一楼提供豆包创建的源码,这里说说播放器模块的使用配置:

一、可以定制界面颜色

在 帖子主元素,例如 id="tz" 标签对应的CSS选择器 #tz { ... } 大括号里加入:

--bg: #666; --color: white; --hlcolor: yellow; --track: gray;

其中,--bg 变量是播放器面板背景色,--color 是前景色、按钮边框颜色,--hlcolor 是LRC高亮颜色、按钮颜色、进度指示色,--track 是播放进度条底色。

二、引用CSS资源

参照帖子代码第 2 行。 同时,帖子主元素需要 class="pa" 指定引用CSS资源的类选择器。

三、引用播放器JS模块

参照帖子代码第 12 行。注意 script 标签 需要 type=“module" 指定类型,标签内的变量都必须声明。

然后需要提供原生LRC歌词变量,参阅代码第 14 、15 、16 行。内部歌词可以分行谢,也可以用 \n 代替分行。

使用 dbplay(帖子主元素, LRC歌词变量); 调用播放器模块。

马黑黑 发表于 2025-3-18 14:18

【附】豆包创建的”炫酷音频播放器“源码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>炫酷音频播放器</title>
    <style>
      body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #121212;
            color: white;
      }

      .audio-player {
            width: 400px;
            background-color: #222;
            border-radius: 10px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
            padding: 20px;
            text-align: center;
      }

      .audio-player audio {
            width: 100%;
            margin-bottom: 20px;
      }

      .controls {
            display: flex;
            justify-content: center;
            align-items: center;
            margin-bottom: 20px;
      }

      .controls button {
            background-color: #1db954;
            color: white;
            border: none;
            border-radius: 50%;
            width: 50px;
            height: 50px;
            font-size: 20px;
            margin: 0 10px;
            cursor: pointer;
            transition: background-color 0.3s;
      }

      .controls button:hover {
            background-color: #1ed760;
      }

      .progress {
            width: 100%;
            height: 10px;
            background-color: #444;
            border-radius: 5px;
            overflow: hidden;
            margin-bottom: 20px;
      }

      .progress-bar {
            height: 100%;
            background-color: #1db954;
            width: 0;
            border-radius: 5px;
      }

      .lyrics {
            height: 200px;
            overflow-y: auto;
            scrollbar-width: thin;
            scrollbar-color: #1db954 #444;
      }

      .lyrics p {
            margin: 5px 0;
            opacity: 0.5;
            transition: opacity 0.3s;
      }

      .lyrics p.highlight {
            opacity: 1;
            color: #1db954;
      }
    </style>
</head>

<body>
    <div class="audio-player">
      <audio id="audio" src="https://music.163.com/song/media/outer/url?id=1294924781"></audio>
      <div class="controls">
            <button id="play-pause">▶</button>
      </div>
      <div class="progress">
            <div class="progress-bar" id="progress-bar"></div>
      </div>
      <div class="lyrics" id="lyrics"></div>
    </div>

    <script>
      const audio = document.getElementById('audio');
      const playPauseButton = document.getElementById('play-pause');
      const progressBar = document.getElementById('progress-bar');
      const lyricsContainer = document.getElementById('lyrics');

      let isPlaying = false;
      let lyrics = [];

      // 解析 LRC 歌词
      function parseLyrics(lrcText) {
            const lines = lrcText.split('\n');
            for (let line of lines) {
                const match = line.match(/^\[(\d{2}):(\d{2})\.(\d{2,3})\](.*)$/);
                if (match) {
                  const minutes = parseInt(match);
                  const seconds = parseInt(match);
                  const milliseconds = parseInt(match);
                  const text = match;
                  const time = minutes * 60 + seconds + milliseconds / 1000;
                  lyrics.push({ time, text });
                }
            }
            lyrics.sort((a, b) => a.time - b.time);
            for (let lyric of lyrics) {
                const p = document.createElement('p');
                p.textContent = lyric.text;
                lyricsContainer.appendChild(p);
            }
      }

      // 更新播放进度条
      function updateProgress() {
            const progress = (audio.currentTime / audio.duration) * 100;
            progressBar.style.width = `${progress}%`;

            // 更新歌词高亮
            for (let i = 0; i < lyrics.length; i++) {
                const lyric = lyrics;
                const nextLyric = lyrics;
                const p = lyricsContainer.children;
                if (audio.currentTime >= lyric.time && (!nextLyric || audio.currentTime < nextLyric.time)) {
                  p.classList.add('highlight');
                  // 自动滚动歌词
                  p.scrollIntoView({
                        behavior: 'smooth',
                        block: 'center'
                  });
                } else {
                  p.classList.remove('highlight');
                }
            }
      }

      // 播放/暂停按钮点击事件
      playPauseButton.addEventListener('click', () => {
            if (isPlaying) {
                audio.pause();
                playPauseButton.textContent = '▶';
            } else {
                audio.play();
                playPauseButton.textContent = '⏸';
            }
            isPlaying = !isPlaying;
      });

      // 音频时间更新事件
      audio.addEventListener('timeupdate', updateProgress);

      // 模拟加载 LRC 歌词
      const lrcText = `
孟美岐:
每天起床第一句 先给自己打个气
吴宣仪:
每次多吃一粒米 都要说声对不起
段奥娟:
魔镜魔镜看看我 我的锁骨在哪里
紫宁:
美丽 我要美丽 我要变成万人迷
合:
Pose pose
我要变成万人迷
Pose pose
徐梦洁:
为了变成小蛮腰 天天提着一口气
赖美云:
为了穿上比基尼 吃草吃成沙拉精
傅菁:
天生丽质难自弃 可惜吃啥我都不腻
合:
努力 我要努力 我要变成万人迷
李紫婷/赖美云/紫宁/徐梦洁:
Wow
吴宣仪/孟美岐/段奥娟/傅菁:
卡路里卡路里卡路
卡路里卡路里卡路
卡路里卡路里卡路
卡路里卡路里卡路
合:
卡路里我的天敌
杨超越:
燃烧我的卡路里
合:
拜拜 甜甜圈 珍珠奶茶方便面
火锅米饭大盘鸡
孟美岐/吴宣仪:
拿走拿走别客气
合:
拜拜 咖啡因 戒掉可乐戒油腻
沙发外卖玩游戏
Yamy/Sunnee:
别再熬夜伤身体
合:
来来 后转体 高温瑜伽仰卧起
动感单车普拉提
赖美云/徐梦洁:
保温杯里泡枸杞
合:
来来 深呼吸 晨跑夜跑游几米
平板哑铃划船机 不达目的不放弃
吴宣仪:
为了变成小蛮腰 天天提着一口气
孟美岐:
为了穿上比基尼 吃草吃成沙拉精
李紫婷:
天生丽质难自弃 可惜吃啥我都不腻
合:
努力 我要努力 我要变成万人迷
李紫婷/赖美云/紫宁/徐梦洁:
Wow
吴宣仪/孟美岐/段奥娟/傅菁:
卡路里卡路里卡路
卡路里卡路里卡路
卡路里卡路里卡路
卡路里卡路里卡路
合:
卡路里我的天敌
杨超越:
燃烧我的卡路里
合:
拜拜 甜甜圈 珍珠奶茶方便面
火锅米饭大盘鸡 拿走拿走别客气
拜拜 咖啡因 戒掉可乐戒油腻
沙发外卖玩游戏 别再熬夜伤身体
来来 后转体 高温瑜伽仰卧起
动感单车普拉提 保温杯里泡枸杞
来来 深呼吸 晨跑夜跑游几米
平板哑铃划船机 不达目的不放弃
Yamy/Sunnee(Rap):
Yamy:
奇了怪了 小的时候明明是 妈妈说
吃光盘中餐粒粒 皆辛苦
Sunnee:
直到最爱的裙子的扣子都系不上了
Yamy:
原来吃得掉 甩不掉 更辛苦
Yamy:
希望 体重 秤是坏的
Sunnee:
帅哥 爱唐代的
合:
不如跟着节奏没在怕的 努努力
别让卡路里卡路里 卡住你
不达目的不放弃
杨超越:
燃烧我的卡路里
合:
拜拜 甜甜圈 珍珠奶茶方便面
火锅米饭大盘鸡 拿走拿走别客气
拜拜 咖啡因 戒掉可乐戒油腻
沙发外卖玩游戏 别再熬夜伤身体
来来 后转体 高温瑜伽仰卧起
动感单车普拉提 保温杯里泡枸杞
来来 深呼吸 晨跑夜跑游几米
平板哑铃划船机 不达目的不放弃
不放弃
燃烧我的卡路里
不放弃
燃烧我的卡路里
我要变成万人迷
-- End --
`;
      parseLyrics(lrcText);
    </script>
</body>

</html>

马黑黑 发表于 2025-3-18 14:21

上面是第一版源码,功能不太完整。要求豆包改进,这是第二版也是终版源码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>炫酷音频播放器</title>
    <style>
      body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #121212;
            color: white;
      }

      .audio-player {
            width: 400px;
            background-color: #222;
            border-radius: 10px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
            padding: 20px;
            text-align: center;
      }

      .audio-player audio {
            width: 100%;
            margin-bottom: 20px;
      }

      .controls {
            display: flex;
            justify-content: center;
            align-items: center;
            margin-bottom: 20px;
      }

      .controls button {
            background-color: #1db954;
            color: white;
            border: none;
            border-radius: 50%;
            width: 50px;
            height: 50px;
            font-size: 20px;
            margin: 0 10px;
            cursor: pointer;
            transition: background-color 0.3s;
      }

      .controls button:hover {
            background-color: #1ed760;
      }

      .progress {
            width: 100%;
            height: 10px;
            background-color: #444;
            border-radius: 5px;
            overflow: hidden;
            margin-bottom: 20px;
            cursor: pointer;
      }

      .progress-bar {
            height: 100%;
            background-color: #1db954;
            width: 0;
            border-radius: 5px;
      }

      .lyrics {
            height: 200px;
            padding: 8px 0;
            overflow: hidden;
      }

      .lyrics p {
            margin: 5px 0;
            font-size: 15px;
            opacity: 0.5;
            transition: opacity 0.5s;
      }

      .lyrics p.highlight {
            opacity: 1;
            font-size: 18px;
            font-weight: bold;
            color: #1db954;
      }
    </style>
</head>

<body>
    <div class="audio-player">
      <audio id="audio" src="https://music.163.com/song/media/outer/url?id=1294924781" autoplay loop></audio>
      <div class="controls">
            <button id="play-pause">▶</button>
      </div>
      <div class="progress" id="progress">
            <div class="progress-bar" id="progress-bar"></div>
      </div>
      <div class="lyrics" id="lyrics"></div>
    </div>

    <script>
      const audio = document.getElementById('audio');
      const playPauseButton = document.getElementById('play-pause');
      const progress = document.getElementById('progress');
      const progressBar = document.getElementById('progress-bar');
      const lyricsContainer = document.getElementById('lyrics');

      let isPlaying = false;
      let lyrics = [];

      // 解析 LRC 歌词
      function parseLyrics(lrcText) {
            const lines = lrcText.split('\n');
            for (let line of lines) {
                const match = line.match(/^\[(\d{2}):(\d{2})\.(\d{2,3})\](.*)$/);
                if (match) {
                  const minutes = parseInt(match);
                  const seconds = parseInt(match);
                  const milliseconds = parseInt(match);
                  const text = match;
                  const time = minutes * 60 + seconds + milliseconds / 1000;
                  lyrics.push({ time, text });
                }
            }
            lyrics.sort((a, b) => a.time - b.time);
            for (let lyric of lyrics) {
                const p = document.createElement('p');
                p.textContent = lyric.text;
                lyricsContainer.appendChild(p);
            }
      }

      // 更新播放进度条
      function updateProgress() {
            const progressValue = (audio.currentTime / audio.duration) * 100;
            progressBar.style.width = `${progressValue}%`;

            // 更新歌词高亮
            for (let i = 0; i < lyrics.length; i++) {
                const lyric = lyrics;
                const nextLyric = lyrics;
                const p = lyricsContainer.children;
                if (audio.currentTime >= lyric.time && (!nextLyric || audio.currentTime < nextLyric.time)) {
                  p.classList.add('highlight');
                  // 自动滚动歌词
                  p.scrollIntoView({
                        behavior: 'smooth',
                        block: 'center'
                  });
                } else {
                  p.classList.remove('highlight');
                }
            }
      }

      // 播放/暂停按钮点击事件
      playPauseButton.addEventListener('click', () => {
            if (isPlaying) {
                audio.pause();
                playPauseButton.textContent = '▶';
            } else {
                audio.play();
                playPauseButton.textContent = '⏸';
            }
            isPlaying = !isPlaying;
      });

      // 音频时间更新事件
      audio.addEventListener('timeupdate', updateProgress);

      // 进度条点击事件
      progress.addEventListener('click', (event) => {
            const rect = progress.getBoundingClientRect();
            const clickX = event.clientX - rect.left;
            const progressWidth = rect.width;
            const clickPercentage = clickX / progressWidth;
            const newTime = clickPercentage * audio.duration;
            audio.currentTime = newTime;
      });

      // 模拟加载 LRC 歌词
      const lrcText = `
孟美岐:
每天起床第一句 先给自己打个气
吴宣仪:
每次多吃一粒米 都要说声对不起
段奥娟:
魔镜魔镜看看我 我的锁骨在哪里
紫宁:
美丽 我要美丽 我要变成万人迷
合:
Pose pose
我要变成万人迷
Pose pose
徐梦洁:
为了变成小蛮腰 天天提着一口气
赖美云:
为了穿上比基尼 吃草吃成沙拉精
傅菁:
天生丽质难自弃 可惜吃啥我都不腻
合:
努力 我要努力 我要变成万人迷
李紫婷/赖美云/紫宁/徐梦洁:
Wow
吴宣仪/孟美岐/段奥娟/傅菁:
卡路里卡路里卡路
卡路里卡路里卡路
卡路里卡路里卡路
卡路里卡路里卡路
合:
卡路里我的天敌
杨超越:
燃烧我的卡路里
合:
拜拜 甜甜圈 珍珠奶茶方便面
火锅米饭大盘鸡
孟美岐/吴宣仪:
拿走拿走别客气
合:
拜拜 咖啡因 戒掉可乐戒油腻
沙发外卖玩游戏
Yamy/Sunnee:
别再熬夜伤身体
合:
来来 后转体 高温瑜伽仰卧起
动感单车普拉提
赖美云/徐梦洁:
保温杯里泡枸杞
合:
来来 深呼吸 晨跑夜跑游几米
平板哑铃划船机 不达目的不放弃
吴宣仪:
为了变成小蛮腰 天天提着一口气
孟美岐:
为了穿上比基尼 吃草吃成沙拉精
李紫婷:
天生丽质难自弃 可惜吃啥我都不腻
合:
努力 我要努力 我要变成万人迷
李紫婷/赖美云/紫宁/徐梦洁:
Wow
吴宣仪/孟美岐/段奥娟/傅菁:
卡路里卡路里卡路
卡路里卡路里卡路
卡路里卡路里卡路
卡路里卡路里卡路
合:
卡路里我的天敌
杨超越:
燃烧我的卡路里
合:
拜拜 甜甜圈 珍珠奶茶方便面
火锅米饭大盘鸡 拿走拿走别客气
拜拜 咖啡因 戒掉可乐戒油腻
沙发外卖玩游戏 别再熬夜伤身体
来来 后转体 高温瑜伽仰卧起
动感单车普拉提 保温杯里泡枸杞
来来 深呼吸 晨跑夜跑游几米
平板哑铃划船机 不达目的不放弃
Yamy/Sunnee(Rap):
Yamy:
奇了怪了 小的时候明明是 妈妈说
吃光盘中餐粒粒 皆辛苦
Sunnee:
直到最爱的裙子的扣子都系不上了
Yamy:
原来吃得掉 甩不掉 更辛苦
Yamy:
希望 体重 秤是坏的
Sunnee:
帅哥 爱唐代的
合:
不如跟着节奏没在怕的 努努力
别让卡路里卡路里 卡住你
不达目的不放弃
杨超越:
燃烧我的卡路里
合:
拜拜 甜甜圈 珍珠奶茶方便面
火锅米饭大盘鸡 拿走拿走别客气
拜拜 咖啡因 戒掉可乐戒油腻
沙发外卖玩游戏 别再熬夜伤身体
来来 后转体 高温瑜伽仰卧起
动感单车普拉提 保温杯里泡枸杞
来来 深呼吸 晨跑夜跑游几米
平板哑铃划船机 不达目的不放弃
不放弃
燃烧我的卡路里
不放弃
燃烧我的卡路里
我要变成万人迷
-- End --
`;
      parseLyrics(lrcText);
    </script>
</body>

</html>

马黑黑 发表于 2025-3-18 14:24

我在豆包源码的基础上封装的CSS代码(配套做贴需要):

.pa {
    --bg: #1a3b5f;
    --color: #c8f9dc;
    --hlcolor: #e8cf11;
    --track: #eee;
    width: 1024px;
    height: 640px;
    display: grid;
    place-items: center;
    background: #eee;
    box-shadow: 2px 2px 10px rgba(0,0,0,.6);
    z-index: 1;
    position: relative;
    margin: 20px auto;
}

.audio-player {
    position: fixed;
    left: 20px;
    bottom: 20px;
    width: 400px;
    background: var(--bg);
    border-radius: 10px;
    box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
    padding: 10px;
    text-align: center;
}

.lyrics {
    height: 120px;
    padding: 8px 0;
    overflow: hidden;
    color: var(--color);
}

.lyrics p {
    margin: 5px 0;
    font-size: 15px;
    opacity: 0.5;
    transition: opacity 0.5s;
}

.lyrics p.highlight {
    opacity: 1;
    font-size: 18px;
    font-weight: bold;
    color: var(--hlcolor);
}

.controls {
    display: grid;
    place-items: center;
    margin-top: 10px;
}

.controls button {
    background: none;
    border: 3px solid var(--color);
    border-radius: 50%;
    width: 40px;
    height: 40px;
    cursor: pointer;
    transition: 0.3s;
    display: grid;
    place-items: center;
    position: relative;
}

.controls button::after {
    position: absolute;
    content: '';
    width: 50%;
    height: 50%;
    background: var(--hlcolor);
    clip-path: var(--clip);
}

.controls button:hover {
    filter: invert(.2);
}

.progress {
    width: 100%;
    height: 10px;
    background: var(--track);
    border-radius: 5px;
    overflow: hidden;
    margin-top: 10px;
    cursor: pointer;
}

.progress-bar {
    height: 100%;
    background: var(--hlcolor);
    width: 0;
    border-radius: 5px;
}

.play {
    --clip: polygon(10% 0, 100% 50%, 10% 100%);
}

.pause {
    --clip: polygon(40% 0, 40% 100%, 20% 100%, 20% 0, 80% 0, 80% 100%, 60% 100%, 60% 0);
}

.vid {
    position: absolute;
    width: 100%;
    height: 100%;
    object-fit: cover;
    mask: radial-gradient(transparent 20%, red);
    -webkit-mask: radial-gradient(transparent 20%, red);
    pointer-events: none;
}

马黑黑 发表于 2025-3-18 14:25

然后是 JS ES模块:

export function dbplay(pa, lrcText) {
    if (pa instanceof Element === false || !lrcText) return;

    pa.innerHTML += `
      <div class="audio-player">
            <div class="lyrics" id="lyrics"></div>
            <div class="controls">
                <button id="play-pause" class="pause"></button>
            </div>
            <div class="progress" id="progress">
                <div class="progress-bar" id="progress-bar"></div>
            </div>
      </div>
    `;

    const audio = pa.querySelector('audio');
    const playPauseButton = document.getElementById('play-pause');
    const progress = document.getElementById('progress');
    const progressBar = document.getElementById('progress-bar');
    const lyricsContainer = document.getElementById('lyrics');
    const vids = pa.querySelectorAll('video');

    let lyrics = [];

    function parseLyrics(lrcText) {
      const lines = lrcText.split('\n');
      for (let line of lines) {
            const match = line.match(/^\[(\d{2}):(\d{2})\.(\d{2,3})\](.*)$/);
            if (match) {
                const minutes = parseInt(match);
                const seconds = parseInt(match);
                const milliseconds = parseInt(match);
                const text = match;
                const time = minutes * 60 + seconds + milliseconds / 1000;
                lyrics.push({ time, text });
            }
      }
      lyrics.sort((a, b) => a.time - b.time);
      for (let lyric of lyrics) {
            const p = document.createElement('p');
            p.textContent = lyric.text;
            lyricsContainer.appendChild(p);
      }
    }

    function updateProgress() {
      const progressValue = (audio.currentTime / audio.duration) * 100;
      progressBar.style.width = `${progressValue}%`;
      for (let i = 0; i < lyrics.length; i++) {
            const lyric = lyrics;
            const nextLyric = lyrics;
            const p = lyricsContainer.children;
            if (audio.currentTime >= lyric.time && (!nextLyric || audio.currentTime < nextLyric.time)) {
                p.classList.add('highlight');
                p.scrollIntoView({ behavior: 'smooth', block: 'center' });
            } else {
                p.classList.remove('highlight');
            }
      }
    }

    function mState() {
      playPauseButton.className = audio.paused ? 'play' : 'pause';
      audio.paused ? playvids(vids, false) : playvids(vids, true);
    }

    function playvids(vids, flag) {
      if(!vids) return;
      vids.forEach(vid => flag ? vid.play() : vid.pause());
    }

    playPauseButton.addEventListener('click', () => {
      audio.paused ? audio.play() : audio.pause();
    });

    audio.addEventListener('timeupdate', updateProgress);
    audio.addEventListener('playing', mState);
    audio.addEventListener('pause', mState);

    progress.addEventListener('click', (event) => {
      const rect = progress.getBoundingClientRect();
      const clickX = event.clientX - rect.left;
      const progressWidth = rect.width;
      const clickPercentage = clickX / progressWidth;
      const newTime = clickPercentage * audio.duration;
      audio.currentTime = newTime;
    });

    parseLyrics(lrcText);
};

马黑黑 发表于 2025-3-18 14:32

帖子代码结构:

<style>
    @import 'https://638183.freep.cn/638183/web/ku/dbplayer.css';
    #tz { --bg: #444; --color: #eee; --hlcolor: #00ff00; --track: #d9d9d9;}
</style>

<div id="tz" class="pa">
    <audio src="音乐地址" autoplay loop></audio>
    <video class="vid" src="视频地址" loop muted></video>
</div>

<script type="module">
import { dbplay } from 'https://638183.freep.cn/638183/web/ku/dbplayer.js';

var lrc = `
卡路里
……
`;

dbplay(tz,lrc);
</script>

花飞飞 发表于 2025-3-18 14:44

艾玛,一路看下来。这是手把手教学怎么用豆包制作音频播放器。。。AI使用实战课程由此开启{:4_170:}

花飞飞 发表于 2025-3-18 14:45

强烈请求白老师公布咒语,上酒 上茶上花上美女{:4_204:}{:4_191:}{:4_190:}{:4_181:}

花飞飞 发表于 2025-3-18 14:47

音频小播直接独立了,还能控制主贴动态,很特别,耳目一新。。。

花飞飞 发表于 2025-3-18 14:48

先狠狠支持一下,迟点细细学习代码组合

朵拉 发表于 2025-3-18 15:47

手机上看 图片和播放器是分离的?{:4_190:}
还有一丢丢怎挡住我的回帖了~~{:4_173:}

梦江南 发表于 2025-3-18 16:15

老师厉害,佩服!{:4_187:}

红影 发表于 2025-3-18 16:37

这个音频不跟着图片了,完全自己独立的{:4_173:}

红影 发表于 2025-3-18 16:38

学习一下豆包做的播放器以及如何改为适合论坛的方式,黑黑辛苦了{:4_187:}

红影 发表于 2025-3-18 16:53

是这句position: fixed;吧,去试了一下改成absolute就可以跟着图片了{:4_173:}

马黑黑 发表于 2025-3-18 18:18

朵拉 发表于 2025-3-18 15:47
手机上看 图片和播放器是分离的?
还有一丢丢怎挡住我的回帖了~~

肯定受影响。目前没有考虑移动端的渲染问题

马黑黑 发表于 2025-3-18 18:20

红影 发表于 2025-3-18 16:53
是这句position: fixed;吧,去试了一下改成absolute就可以跟着图片了

跟随图片之后,网页就会被绑架:只要歌词同步运行中,页面总会被翻到歌词所在的视口

马黑黑 发表于 2025-3-18 18:20

红影 发表于 2025-3-18 16:38
学习一下豆包做的播放器以及如何改为适合论坛的方式,黑黑辛苦了

{:4_190:}
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 卡路里