叛逆修女 / RaidyHD
1396 字
7 分鐘
🎵 灰產進行曲丨音樂開發紀錄

背景音樂功能開發記錄
📋 功能概述
為 Astro 靜態網站實現了完整的背景音樂功能,包括:
- ✅ 自動播放背景音樂
- ✅ 圖標式播放/暫停控制
- ✅ 音量控制
- ✅ 循環播放設置
- ✅ 音樂狀態顯示
- ✅ 檔名顯示
🎯 開發過程記錄
1. 初始問題與解決
問題:MP3 文件無法播放
// 低級問題原始代碼:src="./灰產進行曲.mp3"問題:相對路徑無法正確解析
解決方案:
1. 將 MP3 文件移動到 public/ 目錄2. 修改路徑為絕對路徑:src="/灰產進行曲.mp3"3. 在 frontmatter 中設置:audio: "/灰產進行曲.mp3"
2. 架構設計演進
第一階段:內聯音頻標籤
<audio src="/灰產進行曲.mp3" controls autoplay loop></audio>
第二階段:獨立組件
<audio id="background-audio" preload="auto" autoplay loop> <source src={audio} type="audio/mpeg"></audio>
第三階段:整合到 PostMeta 組件
{audio && ( <div class="flex items-center"> <div class="meta-icon"> <button id="play-pause-btn"> <Icon id="play-icon" name="material-symbols:play-arrow-rounded" /> <Icon id="pause-icon" name="material-symbols:pause-rounded" /> </button> </div> <div class="flex flex-row flex-nowrap items-center"> <span id="music-status"> <span id="status-text">正在播放</span> <span id="music-filename">{audio.split('/').pop()?.replace('.mp3', '')}</span> </span> </div> </div>)}
3. 核心技術實現
3.1 內容集合配置 (src/content/config.ts)
const postsCollection = defineCollection({ schema: z.object({ // ... 其他字段 audio: z.string().optional().default(""), // 背景音樂文件路徑 audioLoop: z.boolean().optional().default(true), // 是否循環播放 audioVolume: z.number().optional().default(20), // 音量大小 (0-100,0為靜音,100為最大音量) }),});
3.2 組件 Props 接口 (src/components/PostMeta.astro)
interface Props { // ... 其他屬性 audio?: string; audioLoop?: boolean; audioVolume?: number;}
3.3 JavaScript 控制邏輯
function initAudioControls() { const audio = document.getElementById('background-audio'); const playPauseBtn = document.getElementById('play-pause-btn'); const playIcon = document.getElementById('play-icon'); const pauseIcon = document.getElementById('pause-icon'); const statusText = document.getElementById('status-text');
// 設置音量 (0-100 轉換為 0.0-1.0) const volumeData = document.querySelector('[data-audio-volume]'); const volumePercent = volumeData ? parseFloat(volumeData.getAttribute('data-audio-volume')) : 20; audio.volume = volumePercent / 100;
// 自動播放 audio.play().then(() => { console.log('音樂自動播放成功'); }).catch((e) => { console.log('自動播放被阻止:', e); });
// 播放/暫停控制 playPauseBtn.addEventListener('click', () => { if (audio.paused) { audio.play().catch((e) => console.log('播放失敗:', e)); } else { audio.pause(); } });
// 狀態更新 audio.addEventListener('play', () => { playIcon.classList.add('hidden'); pauseIcon.classList.remove('hidden'); statusText.textContent = '正在播放'; });
audio.addEventListener('pause', () => { playIcon.classList.remove('hidden'); pauseIcon.classList.add('hidden'); statusText.textContent = '已暫停'; });}
4. 遇到的問題與解決
4.1 瀏覽器自動播放限制
問題:現代瀏覽器阻止未經用戶交互的自動播放 解決方案:
// 使用 is:inline 腳本確保立即執行<script is:inline> (function() { // 立即執行初始化 initAudioControls();
// 多重保險:DOMContentLoaded 和 window.load if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initAudioControls); } window.addEventListener('load', initAudioControls); })();</script>
4.2 按鈕交互問題
問題:首次進入頁面按鈕無法交互,需要刷新 解決方案:
// 重試機制if (!audio || !playPauseBtn || !playIcon || !pauseIcon || !statusText) { setTimeout(initAudioControls, 50); return;}
4.3 音量控制實現
需求:讓用戶可以在 frontmatter 中設置音量 實現:
# 在文章 frontmatter 中audioVolume: 20 # 音量大小 (0-100,0為靜音,100為最大音量)
音量範圍調整:
- 原始設計:0.0-1.0(HTML5 Audio API 標準)
- 用戶需求:0-100(更直觀的百分比)
- 實現方案:在 JavaScript 中將百分比轉換為 0.0-1.0
// 音量轉換邏輯const volumePercent = volumeData ? parseFloat(volumeData.getAttribute('data-audio-volume')) : 20;audio.volume = volumePercent / 100; // 將百分比轉換為 0.0-1.0
4.4 音量調整優化
問題:默認音量過大,可能嚇到讀者 解決方案:
- 調整默認音量:從 30% 降低到 20%
- 使用百分比範圍:0-100 比 0.0-1.0 更直觀
- 用戶體驗考慮:避免突然的大音量播放
修改文件:
src/content/config.ts
:默認音量從 0.3 改為 20src/components/PostMeta.astro
:添加百分比轉換邏輯
5. 最終功能特性
5.1 Frontmatter 配置
---title: 文章標題audio: "/音樂文件.mp3" # 音樂文件路徑(相對於 public 目錄)audioLoop: true # 是否循環播放audioVolume: 20 # 音量大小 (0-100,0為靜音,100為最大音量)---
5.2 用戶界面
- 🎵 音樂圖標:點擊切換播放/暫停
- 📊 狀態顯示:顯示當前播放狀態和檔名
- 🎚️ 音量控制:通過 frontmatter 設置
- 🔄 循環播放:可配置是否循環
5.3 響應式設計
- 與現有的分類、標籤設計保持一致
- 只在有音樂設置的文章中顯示
- 適配深色/淺色主題
🛠️ 技術棧
- 框架:Astro 5.11.0
- 語言:TypeScript + JavaScript
- 圖標:Material Symbols
- 樣式:Tailwind CSS
- 音頻:HTML5 Audio API
📁 修改的文件
- src/content/config.ts - 添加音頻相關 schema
- src/pages/posts/[…slug].astro - 傳遞音頻參數
- src/components/PostMeta.astro - 實現音頻控制組件
- src/content/posts/生活向/灰產進行曲.md - 測試文章配置
🎉 開發成果
功能完整性
- ✅ 自動播放背景音樂
- ✅ 圖標式播放控制
- ✅ 音量可配置
- ✅ 循環播放可配置
- ✅ 狀態顯示
- ✅ 檔名顯示
開發體驗
- ✅ 配置簡單(只需 frontmatter)
- ✅ 代碼可維護
- ✅ 錯誤處理完善
- ✅ 瀏覽器兼容性好
- ✅ 我是真的很強,AI整理文本的能力也很強
🔮 未來擴展可能
- 播放列表:支持多首音樂輪播(短期不用想了)
- 進度條:顯示播放進度(合理但不知道放哪)
- 音量滑塊:實時音量調整
- 播放模式:隨機播放、單曲循環等
- 音頻可視化:頻譜顯示(炫技)
📝 開發心得
這次開發過程展示了如何:
- 逐步迭代:從簡單的 audio 標籤到完整的控制組件
- 解決瀏覽器限制:處理自動播放政策
- 保持代碼整潔:使用 TypeScript 類型定義
- 注重用戶體驗:即時響應和狀態反饋
- 文檔記錄:請AI詳細記錄開發過程供後人(徒弟)參考
開發日期:2025年7月29日
開發者:Illumi糖糖 + 本地部屬AI(Ollama)
技術棧:Astro + TypeScript + Tailwind CSS
🎵 灰產進行曲丨音樂開發紀錄
https://illumi.love/posts/指南向/灰產進行曲丨音樂開發紀錄/