最后活跃于 1754739508

Hexo-Theme-Butterfly实现右下角音乐胶囊

LiuShen's Avatar LiuShen 修订了这个 Gist 1754739508. 转到此修订

1 file changed, 174 insertions, 1 deletion

1.readme.md

@@ -1 +1,174 @@
1 - # 说明
1 + ## 🎵 音乐胶囊模块使用说明
2 +
3 + 本仓库提供了一个可集成到 Hexo 主题 **liushen** 的音乐胶囊播放器模块。模块包含四个主要部分:
4 +
5 + * **主题配置文件**
6 + * **布局模板文件**
7 + * **样式文件**
8 + * **前端脚本**
9 +
10 + 本文档将详细介绍它们的放置位置、引用方式和变量配置。
11 +
12 + ---
13 +
14 + ### 1️⃣ 配置文件(根目录)
15 +
16 + **文件:** `_config.liushen.yml`
17 + **位置:** 项目根目录(`blog/_config.liushen.yml`),**不是主题根目录**。
18 +
19 + 该文件用于存放音乐模块的相关配置(如是否启用、播放列表、API 接口等)。
20 + 示例(按需调整):
21 +
22 + ```yaml
23 + # 页脚音乐胶囊
24 + capsule:
25 + enable: true
26 + # 歌单 ID / 单曲 ID
27 + id: 13597135963
28 + # 服务商:netease / qq / xiami / kugou / baidu
29 + server: netease
30 + # 类型:playlist / song
31 + type: playlist
32 + meting_api: https://met.example.com/api?server=:server&type=:type&id=:id&r=:r
33 + volume: 0.8
34 + ```
35 +
36 + ---
37 +
38 + ### 2️⃣ 布局模板文件
39 +
40 + **文件:** `music.pug`
41 + **位置:** `blog/themes/liushen/layout/includes/third-party/music.pug`
42 +
43 + 该文件用于渲染音乐胶囊播放器 UI,需要在 `layout.pug` 中手动引入。
44 +
45 + 在 `blog/themes/liushen/layout/includes/layout.pug` **底部** 添加以下代码(保留现有内容,仅在末尾追加):
46 +
47 + ```pug
48 + if theme.capsule && theme.capsule.enable
49 + include ./third-party/music.pug
50 + ```
51 +
52 + > 📌 该判断会根据 `_config.liushen.yml` 中的 `capsule.enable` 来决定是否加载播放器。
53 +
54 + ---
55 +
56 + ### 3️⃣ 样式文件
57 +
58 + **文件:** `music-capsule.styl`
59 + **位置:** `blog/themes/liushen/source/css/__layout/music-capsule.styl`
60 +
61 + 该位置的`styl`样式表会被自动整合到`main.css`
62 +
63 + #### 💡 样式变量对照表
64 +
65 + 音乐胶囊使用了一些 CSS 变量,这些变量在亮色与暗色模式下分别定义。
66 +
67 + ##### 🌞 亮色模式(默认)
68 +
69 + ```css
70 + /* nav */
71 + --liushen-nav-bg: rgba(255, 255, 255, 0.8);
72 + --liushen-nav-shadow: rgba(133, 133, 133, 0.6) 0px 5px 6px -5px;
73 +
74 + /* ai_summary */
75 + --liushen-title-font-color: #0883b7;
76 + --liushen-maskbg: rgba(255, 255, 255, 0.85);
77 + --liushen-ai-bg: conic-gradient(from 1.5708rad at 50% 50%, #d6b300 0%, #42A2FF 54%, #d6b300 100%);
78 +
79 + /* card */
80 + --liushen-card-bg: #fff;
81 + --liushen-card-secondbg: #f1f3f8;
82 + --liushen-card-border: 1px solid #e3e8f7;
83 +
84 + /* button */
85 + --liushen-button-bg: #f1f3f8;
86 + --liushen-button-hover-bg: $theme-color;
87 +
88 + /* text */
89 + --liushen-text: #4c4948;
90 + --liushen-secondtext: #3c3c43cc;
91 +
92 + /* snackbar */
93 + --snackbar-bg: rgba(255, 255, 255, 0.809);
94 + --snackbar-text: #4c4948;
95 + --snackbar-border: 1px solid rgba(126, 126, 126, 0.527);
96 +
97 + /* menu child */
98 + --menu-child-bg: rgba(255,255,255,0.8);
99 +
100 + /* fancybox */
101 + --liushen-fancybox-bg: rgba(255,255,255,0.5);
102 + --liushen-fancybox-button-color: #000000;
103 + ```
104 +
105 + ##### 🌙 暗色模式
106 +
107 + ```css
108 + [data-theme='dark'] {
109 + /* nav */
110 + --liushen-nav-bg: rgba(18,18,18,.8);
111 + --liushen-nav-shadow: rgba(133, 133, 133, 0) 0px 5px 6px -5px;
112 +
113 + /* ai_summary */
114 + --liushen-maskbg: rgba(0, 0, 0, 0.85);
115 + --liushen-ai-bg: conic-gradient(from 1.5708rad at 50% 50%,rgba(214, 178, 0, 0.46) 0%,rgba(66, 161, 255, 0.53) 54%,rgba(214, 178, 0, 0.49) 100%);
116 +
117 + /* card */
118 + --liushen-card-bg: #2d2d2d;
119 + --liushen-card-secondbg: #3e3f41;
120 + --liushen-card-border: 1px solid #42444a;
121 +
122 + /* button */
123 + --liushen-button-bg: #30343f;
124 + --liushen-button-hover-bg: $theme-color;
125 +
126 + /* text */
127 + --liushen-text: #ffffffb3;
128 + --liushen-secondtext: #a1a2b8;
129 +
130 + /* snackbar */
131 + --snackbar-bg: rgba(48, 48, 48, 0.809);
132 + --snackbar-text: #dfdfdf;
133 + --snackbar-border: 1px solid #cfd4dc40;
134 +
135 + /* menu child */
136 + --menu-child-bg: rgba(18,18,18,0.8);
137 +
138 + /* fancybox */
139 + --liushen-fancybox-bg: rgba(0,0,0,0.5);
140 + --liushen-fancybox-button-color: #ffffff;
141 + }
142 + ```
143 +
144 + > 你可以将这些变量整合到主题的全局变量文件中,或根据配色需求自行调整。
145 +
146 + ---
147 +
148 + ### 4️⃣ 前端脚本
149 +
150 + **文件:** `music.js`
151 + **位置:** 可放在主题的任意 JS 文件中(例如 `blog/themes/liushen/source/js/music.js`)或合并到 `main.js` 中。
152 +
153 + ### 引入方式一(单独文件)
154 +
155 + 在主题 `layout.pug` 的底部或 `additional-js.pug` 中添加:
156 +
157 + ```pug
158 + script(src='/js/music.js')
159 + ```
160 +
161 + #### 引入方式二(合并代码)
162 +
163 + 将 `music.js` 中的代码直接复制到 `main.js` 或其他已加载的脚本文件中。
164 +
165 + ---
166 +
167 + ### 🔗 集成流程总结
168 +
169 + 1. 将 `_config.liushen.yml` 添加到 **项目根目录** 并配置 `capsule.enable: true`。
170 + 2. 将 `music.pug` 放入 `blog/themes/liushen/layout/includes/third-party/`。
171 + 3. 编辑 `layout.pug`,在底部添加 `include ./third-party/music.pug`(带条件判断)。
172 + 4. 将 `music-capsule.styl` 放入 `blog/themes/liushen/source/css/__layout/`。
173 + 5. 将 `music.js` 放入 JS 目录并在页面加载时引入,或者可以添加到任意js文件中。
174 + 6. 根据需要修改 CSS 变量配色。

LiuShen's Avatar LiuShen 修订了这个 Gist 1754739348. 转到此修订

4 files changed, 273 insertions

1.readme.md(文件已创建)

@@ -0,0 +1 @@
1 + # 说明

music-capsule.styl(文件已创建)

@@ -0,0 +1,230 @@
1 + @keyframes changeright
2 + 0%, 50%, 100%
3 + transform: rotate(0deg) scale(1.1)
4 + box-shadow: 0 0 2px #ffffff00
5 + 25%, 75%
6 + transform: rotate(90deg) scale(1.1)
7 + box-shadow: 0 0 14px #ffffff
8 +
9 + @keyframes playingShadow
10 + 0%, 100%
11 + box-shadow: 0 0px 12px -3px #00000000
12 + 50%
13 + box-shadow: 0 0px 12px 0px var(--default-bg-color)
14 +
15 + @keyframes lightBar
16 + 0%, 100%
17 + opacity: 0.1
18 + 60%
19 + opacity: 0.3
20 +
21 + .aplayer.aplayer-narrow
22 + .aplayer-body,
23 + .aplayer-pic
24 + height: 66px
25 + width: 66px
26 +
27 + #nav-music
28 + display: flex
29 + align-items: center
30 + position: fixed
31 + z-index: 10000
32 + bottom: 10px
33 + left: 10px
34 + cursor: pointer
35 + transition: all 0.5s, left 0s
36 + transform-origin: left bottom
37 + box-shadow: var(--liushen-nav-shadow)
38 + border-radius: 40px
39 + overflow: hidden
40 +
41 + &:active
42 + transform: scale(0.97)
43 +
44 + &.playing
45 + border: var(--liushen-card-border)
46 + box-shadow: 0 0px 12px -3px #00000000
47 + animation: playingShadow 5s linear infinite
48 +
49 + .aplayer.aplayer-withlrc
50 + .aplayer-pic
51 + box-shadow: 0 0 14px #ffffffa6
52 + transform: rotate(0deg) scale(1.1)
53 + border-color: white
54 + animation-play-state: running
55 +
56 + .aplayer-info
57 + color: white
58 +
59 + #nav-music-hoverTips
60 + width: 0
61 +
62 + .aplayer
63 + background: var(--default-bg-color)
64 + border: var(--liushen-card-border)
65 + backdrop-filter: saturate(180%) blur(20px)
66 + transform: translateZ(0)
67 +
68 + .aplayer .aplayer-info .aplayer-controller .aplayer-bar-wrap .aplayer-bar .aplayer-played
69 + animation-play-state: running
70 +
71 + &:hover:not(.playing) #nav-music-hoverTips
72 + opacity: 1
73 +
74 + .aplayer.aplayer-withlrc
75 + .aplayer-pic
76 + height: 25px
77 + width: 25px
78 + border-radius: 40px
79 + z-index: 1
80 + transition: 0.3s
81 + transform: rotate(0deg) scale(1)
82 + border: var(--liushen-card-border)
83 + animation: changeright 24s linear infinite
84 + animation-play-state: paused
85 +
86 + .aplayer-info
87 + height: 100%
88 + color: var(--liushen-text)
89 + margin: 0
90 + padding: 0
91 + display: flex
92 + align-items: center
93 +
94 + #nav-music-hoverTips
95 + color: white
96 + background: var(--default-bg-color)
97 + width: 100%
98 + height: 100%
99 + position: absolute
100 + top: 0
101 + left: 0
102 + align-items: center
103 + justify-content: center
104 + display: flex
105 + border-radius: 40px
106 + opacity: 0
107 + font-size: 12px
108 + z-index: 2
109 + transition: 0.3s
110 +
111 + .aplayer
112 + background: var(--liushen-card-bg)
113 + border-radius: 60px
114 + height: 41px
115 + display: flex
116 + margin: 0
117 + transition: 0.3s
118 + border: var(--liushen-card-border)
119 + box-shadow: none
120 +
121 + .aplayer-notice,
122 + .aplayer-miniswitcher,
123 + .aplayer-list
124 + display: none
125 +
126 + .aplayer-body
127 + position: relative
128 + display: flex
129 + align-items: center
130 + min-width: 180px
131 +
132 + .aplayer-info
133 + .aplayer-music
134 + margin: 0
135 + display: flex
136 + align-items: center
137 + padding: 0 12px 0 8px
138 + cursor: pointer
139 + z-index: 1
140 + height: 100%
141 +
142 + .aplayer-title
143 + cursor: pointer
144 + line-height: 1
145 + display: inline-block
146 + white-space: nowrap
147 + max-width: 120px
148 + overflow: hidden
149 + text-overflow: ellipsis
150 + transition: 0.3s
151 + user-select: none
152 +
153 + .aplayer-controller
154 + position: absolute
155 + width: 100%
156 + height: 100%
157 + top: 0
158 + left: 0
159 +
160 + .aplayer-bar-wrap
161 + margin: 0
162 + padding: 0
163 +
164 + .aplayer-bar
165 + height: 100%
166 + background: 0 0
167 +
168 + .aplayer-loaded
169 + display: none
170 +
171 + .aplayer-played
172 + height: 100%
173 + opacity: 0.1
174 + background-color: white !important
175 + animation: lightBar 5s ease infinite
176 + animation-play-state: paused
177 +
178 + .aplayer-pic
179 + pointer-events: none
180 +
181 + .aplayer-button
182 + bottom: 50%
183 + right: 50%
184 + transform: translate(50%, 50%)
185 + margin: 0
186 + transition: 0.3s
187 + pointer-events all
188 +
189 + &:has(.aplayer-button.aplayer-play)
190 + animation-play-state: paused
191 + transform: rotate(0deg) scale(1) !important
192 +
193 + margin-left: 8px
194 +
195 + .aplayer-info .aplayer-controller .aplayer-time,
196 + .aplayer-info .aplayer-music .aplayer-author
197 + display: none
198 +
199 + &.aplayer-withlist .aplayer-info
200 + border: none
201 +
202 + .aplayer-lrc
203 + width: 0
204 + opacity: 0
205 + transition: 0.3s
206 + margin-bottom: -26px
207 +
208 + p.aplayer-lrc-current
209 + color: white
210 + border: none
211 + min-height: 20px
212 + filter: none
213 +
214 + &:after,
215 + &:before
216 + display: none
217 +
218 + p
219 + color: #ffffffb3
220 + filter: blur(.8px)
221 +
222 + @media screen and (min-width: 600px)
223 + #nav-music.stretch .aplayer.aplayer-withlrc .aplayer-lrc
224 + width: 200px
225 + margin-left: 8px
226 + opacity: 1
227 +
228 + .aplayer-thumb
229 + width: 0 !important
230 + height: 0 !important

music.js(文件已创建)

@@ -0,0 +1,39 @@
1 + const liuMusic = {
2 + musicPlaying: false,
3 + isMusicBind: false,
4 +
5 + musicToggle(isMeting = true) {
6 + if (!this.isMusicBind) {
7 + this.musicBind();
8 + }
9 +
10 + const $music = document.querySelector("#nav-music");
11 + const $meting = document.querySelector("meting-js");
12 + const $console = document.getElementById("consoleMusic");
13 +
14 + this.musicPlaying = !this.musicPlaying;
15 + $music?.classList.toggle("playing", this.musicPlaying);
16 + $music?.classList.toggle("stretch", this.musicPlaying);
17 + $console?.classList.toggle("on", this.musicPlaying);
18 +
19 + if (isMeting) {
20 + this.musicPlaying ? $meting?.aplayer?.play() : $meting?.aplayer?.pause();
21 + }
22 + },
23 +
24 + musicBind() {
25 + const $music = document.querySelector("#nav-music");
26 + const $name = document.querySelector("#nav-music .aplayer-music");
27 + const $button = document.querySelector("#nav-music .aplayer-button");
28 +
29 + $name?.addEventListener("click", () => {
30 + $music?.classList.toggle("stretch");
31 + });
32 +
33 + $button?.addEventListener("click", () => {
34 + this.musicToggle(false);
35 + });
36 +
37 + this.isMusicBind = true;
38 + }
39 + };

music.pug(文件已创建)

@@ -0,0 +1,3 @@
1 + div.needEndHide#nav-music
2 + #nav-music-hoverTips(onclick='liuMusic.musicToggle()')= __('music.hit')
3 + meting-js(id=theme.capsule.id server=theme.capsule.server type=theme.capsule.type mutex="true" preload="none" data-lrctype="0" order="random" volume=theme.capsule.volume api=theme.capsule.meting_api)

LiuShen's Avatar LiuShen 修订了这个 Gist 1754738475. 转到此修订

1 file changed, 11 insertions

_comfig.liushen.yml(文件已创建)

@@ -0,0 +1,11 @@
1 + # 页脚音乐胶囊
2 + capsule:
3 + enable: true
4 + # 歌单 ID / 单曲 ID
5 + id: 13597135963
6 + # 服务商:netease / qq / xiami / kugou / baidu
7 + server: netease
8 + # 类型:playlist / song
9 + type: playlist
10 + meting_api: https://met.example.com/api?server=:server&type=:type&id=:id&r=:r
11 + volume: 0.8
上一页 下一页