Skip to Content
🎉 探索 Shopify 的无限可能 结构化知识 + 实战案例,持续更新中...
进阶教程开发一个背景音乐播放器

Shopify主题背景音乐播放器 - 可配置Section完整开发指南

为Shopify主题开发一个功能强大的背景音乐播放器,不仅能营造品牌氛围,还能提供丰富的配置选项和用户交互功能。本指南将带你构建一个企业级的音乐播放器Section。


Section Schema 配置

首先创建完整的 Schema 配置,让用户可以在后台自定义播放器设置:

{ "name": "背景音乐播放器", "tag": "section", "class": "bg-music-section", "settings": [ { "type": "header", "content": "播放器设置" }, { "type": "checkbox", "id": "enable_music", "label": "启用背景音乐", "default": true }, { "type": "checkbox", "id": "auto_play", "label": "自动播放", "default": false, "info": "受浏览器政策限制,需要用户首次交互后才能播放" }, { "type": "select", "id": "play_mode", "label": "播放模式", "default": "loop", "options": [ { "value": "loop", "label": "循环播放" }, { "value": "random", "label": "随机播放" }, { "value": "single", "label": "单曲循环" }, { "value": "once", "label": "播放一次" } ] }, { "type": "range", "id": "default_volume", "label": "默认音量", "min": 0, "max": 100, "step": 5, "unit": "%", "default": 50 }, { "type": "header", "content": "播放器外观" }, { "type": "select", "id": "player_theme", "label": "播放器主题", "default": "dark", "options": [ { "value": "dark", "label": "深色主题" }, { "value": "light", "label": "浅色主题" }, { "value": "gradient", "label": "渐变主题" }, { "value": "brand", "label": "品牌色主题" } ] }, { "type": "select", "id": "player_position", "label": "播放器位置", "default": "bottom-left", "options": [ { "value": "bottom-left", "label": "左下角" }, { "value": "bottom-right", "label": "右下角" }, { "value": "top-left", "label": "左上角" }, { "value": "top-right", "label": "右上角" } ] }, { "type": "select", "id": "player_size", "label": "播放器大小", "default": "medium", "options": [ { "value": "small", "label": "小" }, { "value": "medium", "label": "中" }, { "value": "large", "label": "大" } ] }, { "type": "checkbox", "id": "show_progress", "label": "显示播放进度", "default": true }, { "type": "checkbox", "id": "show_volume_control", "label": "显示音量控制", "default": true } ], "blocks": [ { "type": "music_track", "name": "音乐曲目", "settings": [ { "type": "text", "id": "track_name", "label": "曲目名称", "placeholder": "例如:品牌主题曲" }, { "type": "text", "id": "artist_name", "label": "艺术家", "placeholder": "例如:XXXX" }, { "type": "url", "id": "audio_url", "label": "音频文件链接", "info": "支持 MP3、OGG、AAC 格式,建议文件小于 5MB" }, { "type": "image_picker", "id": "cover_image", "label": "封面图片(可选)" } ] } ], "presets": [ { "name": "背景音乐播放器", "blocks": [ { "type": "music_track", "settings": { "track_name": "示例音乐", "artist_name": "店铺音乐" } } ] } ] }

完整 Section 代码

Section 主体结构 (bg-music.liquid)

{%- if section.settings.enable_music and section.blocks.size > 0 -%} <section id="bg-music-section" class="bg-music-wrapper" data-auto-play="{{ section.settings.auto_play }}" data-play-mode="{{ section.settings.play_mode }}" data-default-volume="{{ section.settings.default_volume }}" data-theme="{{ section.settings.player_theme }}" data-position="{{ section.settings.player_position }}" data-size="{{ section.settings.player_size }}" > <!-- 音频播放器(隐藏的原生播放器) --> <div class="audio-container"> {%- for block in section.blocks -%} {%- case block.type -%} {%- when 'music_track' -%} <audio class="bg-audio-track" data-track-index="{{ forloop.index0 }}" data-track-name="{{ block.settings.track_name | escape }}" data-artist="{{ block.settings.artist_name | escape }}" preload="metadata" {{ block.shopify_attributes }} > <source src="{{ block.settings.audio_url }}" type="audio/mpeg"> <source src="{{ block.settings.audio_url }}" type="audio/ogg"> 您的浏览器不支持音频播放功能 </audio> {%- endcase -%} {%- endfor -%} </div> <!-- 播放器控制界面 --> <div class="music-player-widget {{ section.settings.player_theme }} {{ section.settings.player_position }} {{ section.settings.player_size }}"> <!-- 主控制按钮 --> <button class="player-toggle-btn" aria-label="播放/暂停背景音乐" tabindex="0"> <svg class="play-icon" viewBox="0 0 24 24" fill="currentColor"> <path d="M8 5v14l11-7z"/> </svg> <svg class="pause-icon" viewBox="0 0 24 24" fill="currentColor" style="display: none"> <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/> </svg> </button> <!-- 扩展控制面板 --> <div class="player-controls" style="display: none"> <!-- 音乐信息 --> <div class="track-info"> <div class="track-name">未选择音乐</div> <div class="artist-name"></div> </div> {%- if section.settings.show_progress -%} <!-- 播放进度 --> <div class="progress-container"> <div class="progress-bar"> <div class="progress-fill"></div> <div class="progress-handle"></div> </div> <div class="time-display"> <span class="current-time">0:00</span> <span class="total-time">0:00</span> </div> </div> {%- endif -%} <!-- 控制按钮组 --> <div class="control-buttons"> <button class="prev-btn" aria-label="上一首" title="上一首">⏮</button> <button class="next-btn" aria-label="下一首" title="下一首">⏭</button> <button class="mode-btn" aria-label="播放模式" title="播放模式">🔄</button> {%- if section.settings.show_volume_control -%} <!-- 音量控制 --> <div class="volume-control"> <button class="volume-btn" aria-label="音量控制" title="音量">🔊</button> <div class="volume-slider"> <input type="range" min="0" max="100" value="{{ section.settings.default_volume }}" class="volume-range"> </div> </div> {%- endif -%} </div> </div> <!-- 展开/收起按钮 --> <button class="expand-btn" aria-label="展开播放器" title="展开播放器">⚙️</button> </div> </section> {%- endif -%} ### CSS 样式 (添加到主题样式文件或 Section 内) ```scss /* 背景音乐播放器样式 */ .bg-music-wrapper { .audio-container { position: absolute; opacity: 0; pointer-events: none; } .music-player-widget { position: fixed; z-index: 9999; display: flex; align-items: center; gap: 8px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); /* 位置设置 */ &.bottom-left { bottom: 20px; left: 20px; } &.bottom-right { bottom: 20px; right: 20px; } &.top-left { top: 20px; left: 20px; } &.top-right { top: 20px; right: 20px; } /* 尺寸设置 */ &.small .player-toggle-btn { width: 48px; height: 48px; font-size: 16px; } &.medium .player-toggle-btn { width: 60px; height: 60px; font-size: 20px; } &.large .player-toggle-btn { width: 72px; height: 72px; font-size: 24px; } /* 主题样式 */ &.dark { .player-toggle-btn { background: rgba(0, 0, 0, 0.8); color: white; border: 2px solid rgba(255, 255, 255, 0.2); } .player-controls { background: rgba(0, 0, 0, 0.9); color: white; border: 1px solid rgba(255, 255, 255, 0.1); } } &.light { .player-toggle-btn { background: rgba(255, 255, 255, 0.9); color: #333; border: 2px solid rgba(0, 0, 0, 0.1); } .player-controls { background: rgba(255, 255, 255, 0.95); color: #333; border: 1px solid rgba(0, 0, 0, 0.1); } } &.gradient { .player-toggle-btn { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; } .player-controls { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; } } /* 主控制按钮 */ .player-toggle-btn { border-radius: 50%; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(10px); transition: all 0.3s ease; svg { width: 60%; height: 60%; transition: all 0.2s ease; } &:hover, &:focus { transform: scale(1.05); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); } &.playing { animation: pulse 2s infinite; } &:focus { outline: 2px solid #007AFF; outline-offset: 2px; } } /* 扩展控制面板 */ .player-controls { position: absolute; bottom: 100%; left: 0; margin-bottom: 12px; padding: 16px; border-radius: 12px; backdrop-filter: blur(20px); min-width: 280px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); .track-info { margin-bottom: 12px; .track-name { font-weight: 600; font-size: 14px; margin-bottom: 2px; } .artist-name { font-size: 12px; opacity: 0.7; } } .progress-container { margin-bottom: 12px; .progress-bar { position: relative; height: 4px; background: rgba(255, 255, 255, 0.2); border-radius: 2px; cursor: pointer; margin-bottom: 8px; .progress-fill { height: 100%; background: #007AFF; border-radius: 2px; width: 0%; transition: width 0.1s linear; } .progress-handle { position: absolute; top: 50%; transform: translate(-50%, -50%); width: 12px; height: 12px; background: #007AFF; border-radius: 50%; left: 0%; cursor: grab; opacity: 0; transition: opacity 0.2s ease; } &:hover .progress-handle { opacity: 1; } } .time-display { display: flex; justify-content: space-between; font-size: 11px; opacity: 0.7; } } .control-buttons { display: flex; align-items: center; gap: 12px; button { background: rgba(255, 255, 255, 0.1); border: none; border-radius: 6px; padding: 8px; cursor: pointer; font-size: 14px; transition: all 0.2s ease; &:hover { background: rgba(255, 255, 255, 0.2); transform: translateY(-1px); } } .volume-control { display: flex; align-items: center; gap: 8px; .volume-slider { width: 60px; .volume-range { width: 100%; height: 4px; border-radius: 2px; background: rgba(255, 255, 255, 0.2); outline: none; cursor: pointer; &::-webkit-slider-thumb { appearance: none; width: 12px; height: 12px; border-radius: 50%; background: #007AFF; cursor: pointer; } } } } } } .expand-btn { background: rgba(255, 255, 255, 0.1); border: none; border-radius: 50%; width: 32px; height: 32px; cursor: pointer; font-size: 12px; transition: all 0.2s ease; &:hover { background: rgba(255, 255, 255, 0.2); transform: scale(1.1); } } } } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.5); } 70% { box-shadow: 0 0 0 15px rgba(0, 123, 255, 0); } 100% { box-shadow: 0 0 0 0 rgba(0, 123, 255, 0); } } /* 响应式设计 */ @media (max-width: 768px) { .bg-music-wrapper .music-player-widget { &.small .player-toggle-btn { width: 44px; height: 44px; } &.medium .player-toggle-btn { width: 52px; height: 52px; } &.large .player-toggle-btn { width: 60px; height: 60px; } .player-controls { min-width: 260px; bottom: auto; top: 100%; margin-top: 12px; margin-bottom: 0; } } }

JavaScript 功能实现

class ShopifyMusicPlayer { constructor(sectionElement) { this.section = sectionElement this.audioTracks = [...this.section.querySelectorAll('.bg-audio-track')] this.currentTrackIndex = 0 this.currentAudio = null this.isPlaying = false this.isExpanded = false this.playMode = this.section.dataset.playMode || 'loop' this.autoPlay = this.section.dataset.autoPlay === 'true' this.defaultVolume = parseInt(this.section.dataset.defaultVolume) / 100 || 0.5 this.initializeElements() this.initializeEvents() this.loadTrack(0) this.updatePlayModeButton() if (this.autoPlay) { this.handleFirstInteraction() } } initializeElements() { this.widget = this.section.querySelector('.music-player-widget') this.toggleBtn = this.section.querySelector('.player-toggle-btn') this.expandBtn = this.section.querySelector('.expand-btn') this.controls = this.section.querySelector('.player-controls') this.trackName = this.section.querySelector('.track-name') this.artistName = this.section.querySelector('.artist-name') this.progressBar = this.section.querySelector('.progress-bar') this.progressFill = this.section.querySelector('.progress-fill') this.progressHandle = this.section.querySelector('.progress-handle') this.currentTimeDisplay = this.section.querySelector('.current-time') this.totalTimeDisplay = this.section.querySelector('.total-time') this.prevBtn = this.section.querySelector('.prev-btn') this.nextBtn = this.section.querySelector('.next-btn') this.modeBtn = this.section.querySelector('.mode-btn') this.volumeBtn = this.section.querySelector('.volume-btn') this.volumeRange = this.section.querySelector('.volume-range') this.playIcon = this.section.querySelector('.play-icon') this.pauseIcon = this.section.querySelector('.pause-icon') } initializeEvents() { // 主控制按钮 this.toggleBtn?.addEventListener('click', () => this.togglePlay()) this.toggleBtn?.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault() this.togglePlay() } }) // 展开按钮 this.expandBtn?.addEventListener('click', () => this.toggleExpand()) // 控制按钮 this.prevBtn?.addEventListener('click', () => this.previousTrack()) this.nextBtn?.addEventListener('click', () => this.nextTrack()) this.modeBtn?.addEventListener('click', () => this.cyclePlayMode()) // 音量控制 this.volumeBtn?.addEventListener('click', () => this.toggleMute()) this.volumeRange?.addEventListener('input', (e) => this.setVolume(e.target.value / 100)) // 进度条控制 this.progressBar?.addEventListener('click', (e) => this.seekTo(e)) // 首次交互处理 document.addEventListener('click', () => this.handleFirstInteraction(), { once: true }) // 键盘快捷键 document.addEventListener('keydown', (e) => this.handleKeyboard(e)) } loadTrack(index) { if (index < 0 || index >= this.audioTracks.length) return if (this.currentAudio) { this.currentAudio.pause() this.currentAudio.removeEventListener('loadedmetadata', this.onLoadedMetadata) this.currentAudio.removeEventListener('timeupdate', this.onTimeUpdate) this.currentAudio.removeEventListener('ended', this.onTrackEnded) } this.currentTrackIndex = index this.currentAudio = this.audioTracks[index] if (!this.currentAudio) return // 更新音乐信息 const trackName = this.currentAudio.dataset.trackName || '未知音乐' const artistName = this.currentAudio.dataset.artist || '未知艺术家' if (this.trackName) this.trackName.textContent = trackName if (this.artistName) this.artistName.textContent = artistName // 设置音量 this.currentAudio.volume = this.defaultVolume if (this.volumeRange) this.volumeRange.value = this.defaultVolume * 100 // 绑定事件 this.onLoadedMetadata = () => this.updateDuration() this.onTimeUpdate = () => this.updateProgress() this.onTrackEnded = () => this.handleTrackEnd() this.currentAudio.addEventListener('loadedmetadata', this.onLoadedMetadata) this.currentAudio.addEventListener('timeupdate', this.onTimeUpdate) this.currentAudio.addEventListener('ended', this.onTrackEnded) } togglePlay() { if (!this.currentAudio) return if (this.isPlaying) { this.pause() } else { this.play() } } async play() { if (!this.currentAudio) return try { await this.currentAudio.play() this.isPlaying = true this.updatePlayButton() this.toggleBtn?.classList.add('playing') } catch (error) { console.error('播放失败:', error) } } pause() { if (!this.currentAudio) return this.currentAudio.pause() this.isPlaying = false this.updatePlayButton() this.toggleBtn?.classList.remove('playing') } updatePlayButton() { if (this.playIcon && this.pauseIcon) { this.playIcon.style.display = this.isPlaying ? 'none' : 'block' this.pauseIcon.style.display = this.isPlaying ? 'block' : 'none' } } previousTrack() { let newIndex = this.currentTrackIndex - 1 if (newIndex < 0) { newIndex = this.audioTracks.length - 1 } this.loadTrack(newIndex) if (this.isPlaying) this.play() } nextTrack() { let newIndex if (this.playMode === 'random') { newIndex = Math.floor(Math.random() * this.audioTracks.length) } else { newIndex = this.currentTrackIndex + 1 if (newIndex >= this.audioTracks.length) { newIndex = 0 } } this.loadTrack(newIndex) if (this.isPlaying) this.play() } cyclePlayMode() { const modes = ['loop', 'random', 'single', 'once'] const currentIndex = modes.indexOf(this.playMode) this.playMode = modes[(currentIndex + 1) % modes.length] this.updatePlayModeButton() // 保存用户偏好 localStorage.setItem('musicPlayerMode', this.playMode) } updatePlayModeButton() { if (!this.modeBtn) return const modeIcons = { loop: '🔄', random: '🔀', single: '🔂', once: '➡️' } this.modeBtn.textContent = modeIcons[this.playMode] || '🔄' this.modeBtn.title = `播放模式: ${this.playMode}` } handleTrackEnd() { switch (this.playMode) { case 'single': this.currentAudio.currentTime = 0 this.play() break case 'once': this.pause() break case 'loop': case 'random': default: this.nextTrack() break } } setVolume(volume) { if (this.currentAudio) { this.currentAudio.volume = Math.max(0, Math.min(1, volume)) } this.updateVolumeButton() } toggleMute() { if (!this.currentAudio) return if (this.currentAudio.volume > 0) { this.previousVolume = this.currentAudio.volume this.setVolume(0) if (this.volumeRange) this.volumeRange.value = 0 } else { const restoreVolume = this.previousVolume || this.defaultVolume this.setVolume(restoreVolume) if (this.volumeRange) this.volumeRange.value = restoreVolume * 100 } } updateVolumeButton() { if (!this.volumeBtn || !this.currentAudio) return const volume = this.currentAudio.volume let icon = '🔊' if (volume === 0) icon = '🔇' else if (volume < 0.3) icon = '🔈' else if (volume < 0.7) icon = '🔉' this.volumeBtn.textContent = icon } updateProgress() { if (!this.currentAudio || !this.progressFill) return const progress = this.currentAudio.currentTime / this.currentAudio.duration this.progressFill.style.width = `${progress * 100}%` if (this.progressHandle) { this.progressHandle.style.left = `${progress * 100}%` } if (this.currentTimeDisplay) { this.currentTimeDisplay.textContent = this.formatTime(this.currentAudio.currentTime) } } updateDuration() { if (!this.currentAudio || !this.totalTimeDisplay) return this.totalTimeDisplay.textContent = this.formatTime(this.currentAudio.duration) } seekTo(event) { if (!this.currentAudio || !this.progressBar) return const rect = this.progressBar.getBoundingClientRect() const clickX = event.clientX - rect.left const progress = clickX / rect.width this.currentAudio.currentTime = progress * this.currentAudio.duration } formatTime(seconds) { if (isNaN(seconds)) return '0:00' const mins = Math.floor(seconds / 60) const secs = Math.floor(seconds % 60) return `${mins}:${secs.toString().padStart(2, '0')}` } toggleExpand() { this.isExpanded = !this.isExpanded if (this.controls) { this.controls.style.display = this.isExpanded ? 'block' : 'none' } if (this.expandBtn) { this.expandBtn.textContent = this.isExpanded ? '✕' : '⚙️' this.expandBtn.setAttribute('aria-label', this.isExpanded ? '收起播放器' : '展开播放器') } } handleFirstInteraction() { if (this.autoPlay && !this.isPlaying) { this.play() } } handleKeyboard(event) { // 只在非输入元素上响应快捷键 if (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA') return switch (event.code) { case 'Space': if (event.ctrlKey) { event.preventDefault() this.togglePlay() } break case 'ArrowLeft': if (event.ctrlKey) { event.preventDefault() this.previousTrack() } break case 'ArrowRight': if (event.ctrlKey) { event.preventDefault() this.nextTrack() } break } } } // 初始化播放器 document.addEventListener('DOMContentLoaded', () => { const musicSection = document.getElementById('bg-music-section') if (musicSection) { new ShopifyMusicPlayer(musicSection) } })

集成到Shopify主题的完整步骤

方法一:作为Section使用(推荐用于特定页面)

1. 创建Section文件

在主题的 sections/ 目录下创建 bg-music.liquid 文件,将上述完整代码复制进去

2. 在主题中引用

在需要显示音乐播放器的模板中添加:

<!-- 在 theme.liquid 的 body 结束标签前 --> {% section 'bg-music' %} <!-- 或在特定页面模板中 --> {% section 'bg-music' %}

3. 后台配置

  1. 进入主题定制器
  2. 添加”背景音乐播放器”Section
  3. 配置播放器设置(主题、位置、音量等)
  4. 添加音乐曲目Block,设置音乐信息和文件链接

方法二:集成到模板设置中(推荐用于全站)

如果你希望在整个网站中都能使用背景音乐播放器,可以将其直接集成到主题设置中。

1. 修改 settings_schema.json

在主题根目录的 config/settings_schema.json 文件中添加以下配置:

{ "name": "背景音乐设置", "settings": [ { "type": "header", "content": "背景音乐播放器" }, { "type": "checkbox", "id": "enable_background_music", "label": "启用背景音乐", "default": false, "info": "在整个网站中启用背景音乐播放器" }, { "type": "checkbox", "id": "music_auto_play", "label": "自动播放", "default": false, "info": "受浏览器政策限制,需要用户首次交互后才能播放" }, { "type": "select", "id": "music_play_mode", "label": "播放模式", "default": "loop", "options": [ { "value": "loop", "label": "循环播放" }, { "value": "random", "label": "随机播放" }, { "value": "single", "label": "单曲循环" }, { "value": "once", "label": "播放一次" } ] }, { "type": "range", "id": "music_default_volume", "label": "默认音量", "min": 0, "max": 100, "step": 5, "unit": "%", "default": 50 }, { "type": "select", "id": "music_player_theme", "label": "播放器主题", "default": "dark", "options": [ { "value": "dark", "label": "深色主题" }, { "value": "light", "label": "浅色主题" }, { "value": "gradient", "label": "渐变主题" }, { "value": "brand", "label": "品牌色主题" } ] }, { "type": "select", "id": "music_player_position", "label": "播放器位置", "default": "bottom-left", "options": [ { "value": "bottom-left", "label": "左下角" }, { "value": "bottom-right", "label": "右下角" }, { "value": "top-left", "label": "左上角" }, { "value": "top-right", "label": "右上角" } ] }, { "type": "select", "id": "music_player_size", "label": "播放器大小", "default": "medium", "options": [ { "value": "small", "label": "小" }, { "value": "medium", "label": "中" }, { "value": "large", "label": "大" } ] }, { "type": "checkbox", "id": "music_show_progress", "label": "显示播放进度", "default": true }, { "type": "checkbox", "id": "music_show_volume_control", "label": "显示音量控制", "default": true }, { "type": "header", "content": "音乐列表" }, { "type": "text", "id": "music_track_1_name", "label": "音乐1 - 曲目名称", "placeholder": "例如:品牌主题曲" }, { "type": "text", "id": "music_track_1_artist", "label": "音乐1 - 艺术家", "placeholder": "例如:音乐制作人" }, { "type": "url", "id": "music_track_1_url", "label": "音乐1 - 文件链接", "info": "支持 MP3、OGG、AAC 格式" }, { "type": "text", "id": "music_track_2_name", "label": "音乐2 - 曲目名称(可选)" }, { "type": "text", "id": "music_track_2_artist", "label": "音乐2 - 艺术家(可选)" }, { "type": "url", "id": "music_track_2_url", "label": "音乐2 - 文件链接(可选)" }, { "type": "text", "id": "music_track_3_name", "label": "音乐3 - 曲目名称(可选)" }, { "type": "text", "id": "music_track_3_artist", "label": "音乐3 - 艺术家(可选)" }, { "type": "url", "id": "music_track_3_url", "label": "音乐3 - 文件链接(可选)" } ] }

2. 在 theme.liquid 中集成播放器

layout/theme.liquid 文件的 </body> 标签前添加:

{%- if settings.enable_background_music -%} {%- assign music_tracks = '' -%} {%- if settings.music_track_1_url != blank -%} {%- assign music_tracks = music_tracks | append: settings.music_track_1_url | append: '|' | append: settings.music_track_1_name | append: '|' | append: settings.music_track_1_artist | append: '||' -%} {%- endif -%} {%- if settings.music_track_2_url != blank -%} {%- assign music_tracks = music_tracks | append: settings.music_track_2_url | append: '|' | append: settings.music_track_2_name | append: '|' | append: settings.music_track_2_artist | append: '||' -%} {%- endif -%} {%- if settings.music_track_3_url != blank -%} {%- assign music_tracks = music_tracks | append: settings.music_track_3_url | append: '|' | append: settings.music_track_3_name | append: '|' | append: settings.music_track_3_artist | append: '||' -%} {%- endif -%} {%- if music_tracks != blank -%} <section id="bg-music-section" class="bg-music-wrapper" data-auto-play="{{ settings.music_auto_play }}" data-play-mode="{{ settings.music_play_mode }}" data-default-volume="{{ settings.music_default_volume }}" data-theme="{{ settings.music_player_theme }}" data-position="{{ settings.music_player_position }}" data-size="{{ settings.music_player_size }}" data-tracks="{{ music_tracks | remove: '||' | split: '||' | join: ',' }}" > <!-- 音频播放器(隐藏的原生播放器) --> <div class="audio-container"> {%- assign tracks_array = music_tracks | remove: '||' | split: '||' -%} {%- for track_data in tracks_array -%} {%- assign track_parts = track_data | split: '|' -%} {%- if track_parts[0] != blank -%} <audio class="bg-audio-track" data-track-index="{{ forloop.index0 }}" data-track-name="{{ track_parts[1] | default: '未知音乐' | escape }}" data-artist="{{ track_parts[2] | default: '未知艺术家' | escape }}" preload="metadata" > <source src="{{ track_parts[0] }}" type="audio/mpeg"> <source src="{{ track_parts[0] }}" type="audio/ogg"> 您的浏览器不支持音频播放功能 </audio> {%- endif -%} {%- endfor -%} </div> <!-- 播放器控制界面 --> <div class="music-player-widget {{ settings.music_player_theme }} {{ settings.music_player_position }} {{ settings.music_player_size }}"> <!-- 主控制按钮 --> <button class="player-toggle-btn" aria-label="播放/暂停背景音乐" tabindex="0"> <svg class="play-icon" viewBox="0 0 24 24" fill="currentColor"> <path d="M8 5v14l11-7z"/> </svg> <svg class="pause-icon" viewBox="0 0 24 24" fill="currentColor" style="display: none"> <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/> </svg> </button> <!-- 扩展控制面板 --> <div class="player-controls" style="display: none"> <!-- 音乐信息 --> <div class="track-info"> <div class="track-name">未选择音乐</div> <div class="artist-name"></div> </div> {%- if settings.music_show_progress -%} <!-- 播放进度 --> <div class="progress-container"> <div class="progress-bar"> <div class="progress-fill"></div> <div class="progress-handle"></div> </div> <div class="time-display"> <span class="current-time">0:00</span> <span class="total-time">0:00</span> </div> </div> {%- endif -%} <!-- 控制按钮组 --> <div class="control-buttons"> <button class="prev-btn" aria-label="上一首" title="上一首">⏮</button> <button class="next-btn" aria-label="下一首" title="下一首">⏭</button> <button class="mode-btn" aria-label="播放模式" title="播放模式">🔄</button> {%- if settings.music_show_volume_control -%} <!-- 音量控制 --> <div class="volume-control"> <button class="volume-btn" aria-label="音量控制" title="音量">🔊</button> <div class="volume-slider"> <input type="range" min="0" max="100" value="{{ settings.music_default_volume }}" class="volume-range"> </div> </div> {%- endif -%} </div> </div> <!-- 展开/收起按钮 --> <button class="expand-btn" aria-label="展开播放器" title="展开播放器">⚙️</button> </div> </section> <!-- 添加样式和脚本 --> <style> /* 这里放入之前的 CSS 样式代码 */ </style> <script> /* 这里放入之前的 JavaScript 代码 */ </script> {%- endif -%} {%- endif -%}

3. 后台配置步骤

  1. 进入 Shopify 后台
  2. 前往”在线商店” → “主题”
  3. 点击”自定义”
  4. 在主题设置中找到”背景音乐设置”部分
  5. 启用背景音乐并配置相关设置
  6. 添加音乐文件链接和信息
  7. 保存设置

4. 上传音乐文件

  • 将音乐文件上传到 Shopify 后台的”文件”部分
  • 复制文件URL用于主题设置配置
  • 建议使用MP3格式,文件大小控制在5MB以内

高级功能与最佳实践

性能优化

  • 懒加载:音频文件仅在需要时加载,使用 preload="metadata"
  • 文件压缩:建议音乐文件压缩至合适的比特率(128-192kbps)
  • 缓存策略:利用浏览器缓存,避免重复下载

用户体验优化

  • 记住偏好:使用 localStorage 保存用户的音量、播放模式设置
  • 自动播放策略:遵循浏览器自动播放政策,提供友好的播放提示
  • 无障碍支持:完整的键盘导航和屏幕阅读器支持

故障排除

常见问题解决

  1. 音乐无法自动播放

    • 检查浏览器自动播放政策
    • 确保用户已有交互行为
  2. 音频文件加载失败

    • 验证文件URL是否正确
    • 检查文件格式兼容性
  3. 样式显示异常

    • 检查CSS样式是否被主题样式覆盖
    • 验证响应式断点设置
  4. 性能问题

    • 减少音频文件大小
    • 优化播放器初始化时机

扩展功能建议

  • 播放列表管理:支持用户自定义播放列表
  • 音效可视化:添加音频频谱动画
  • 社交分享:分享正在播放的音乐
  • AI推荐:根据用户行为推荐音乐

通过这个完整的背景音乐播放器,你可以为Shopify店铺创造独特的品牌氛围,提升用户体验和品牌记忆度。

最后更新时间: