new: Added music collection page

This commit is contained in:
2024-12-25 23:58:02 +08:00
parent 1c23f2ac25
commit 2986e30558
17 changed files with 1678 additions and 0 deletions

View File

@@ -7,6 +7,7 @@
--dark-secondary-text-color: #a3a2ac;
--dark-background-color: #131318;
--dark-panel-color: #1c1b1f;
/* light mode */
--light-primary-color: #6d6faa;
@@ -16,6 +17,7 @@
--light-secondary-text-color: #5f5e67;
--light-background-color: #fbf8ff;
--light-panel-color: #e2e0f9;
/* used color */
--primary-color: #0;
@@ -25,6 +27,7 @@
--secondary-text-color: #0;
--background-color: #0;
--panel-color: #0;
}
@font-face {

View File

@@ -0,0 +1,755 @@
@font-face {
font-weight: normal;
font-style: normal;
font-family: 'fontello';
src: url('../../../assets/css/webfonts/fontello.eot?77128880');
src: url('../../../assets/css/webfonts/fontello.eot?77128880#iefix') format('embedded-opentype'),
url('../../../assets/css/webfonts/fontello.woff?77128880') format('woff'),
url('../../../assets/css/webfonts/fontello.ttf?77128880') format('truetype'),
url('../../../assets/css/webfonts/fontello.svg?77128880#fontello') format('svg');
}
.meplayer-container {
position: relative;
box-sizing: border-box;
width: 100%;
height: 90px;
background: var(--panel-color);
box-shadow: 0 0 20px rgba(0, 0, 0, .18);
border-radius: 14px 14px 0 0;
}
.meplayer-container .meplayer-info {
position: relative;
left: 0;
opacity: 1;
}
.meplayer-container .meplayer-info-cover {
overflow: hidden;
position: absolute;
top: 0;
left: 0;
height: 90px;
padding-right: 20px;
-webkit-transition: all .6s cubic-bezier(0, .36, .51, 1.39);
transition: all .6s cubic-bezier(0, .36, .51, 1.39);
}
.meplayer-container.meplayer-isplaying .meplayer-info-cover {
left: -90px;
opacity: 0;
}
.meplayer-container .meplayer-info-cover img {
width: 78px;
height: 78px;
box-shadow: 0 0 20px rgba(0, 0, 0, .35);
}
.meplayer-container .meplayer-meta {
float: left;
margin-left: 110px;
-webkit-transition: all .6s cubic-bezier(0, .36, .51, 1.39);
transition: all .6s cubic-bezier(0, .36, .51, 1.39);
}
.meplayer-container.meplayer-isplaying .meplayer-meta {
margin-left: 10px;
-webkit-transform: scale(.85, .85);
transform: scale(.85, .85);
}
.meplayer-container.meplayer-isplaying .meplayer-meta .meplayer-meta-title {
margin-top: 4px;
}
.meplayer-container.meplayer-isplaying .meplayer-meta .meplayer-meta-time-tick {
-webkit-transition: all .6s cubic-bezier(0, .36, .51, 1.39) .65s;
transition: all .6s cubic-bezier(0, .36, .51, 1.39) .65s;
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
.meplayer-container .meplayer-meta .meplayer-meta-time-tick {
font-size: 14px;
margin-top: 10px;
-webkit-transform: translateY(10px);
transform: translateY(10px);
letter-spacing: 1px;
opacity: 0;
color: var(--primary-text-color);
}
.meplayer-container .meplayer-meta-title {
font-size: 16px;
font-weight: bold;
margin-top: 27px;
margin-bottom: 2px;
-webkit-transition: all .6s cubic-bezier(0, .36, .51, 1.39);
transition: all .6s cubic-bezier(0, .36, .51, 1.39);
letter-spacing: 1px;
color: var(--primary-text-color);
}
.meplayer-container .meplayer-meta-author {
font-size: 14px;
color: var(--secondary-text-color);
}
.meplayer-container .meplayer-spectrum {
position: absolute;
top: 50%;
left: 50%;
display: block;
width: 0;
height: 30px;
margin-top: -15px;
margin-left: -120px;
-webkit-transition: all .7s cubic-bezier(.17, .67, .45, 1.26) .1s;
transition: all .7s cubic-bezier(.17, .67, .45, 1.26) .1s;
-webkit-transform: translateX(110px);
transform: translateX(110px);
opacity: 0;
}
.meplayer-container.meplayer-isplaying .meplayer-spectrum {
width: 220px;
-webkit-transform: translateX(0);
transform: translateX(0);
opacity: 1;
}
.meplayer-container.meplayer-haslrc .meplayer-spectrum {
display: none;
}
.meplayer-container .meplayer-lyric {
position: absolute;
z-index: -2;
top: 50%;
left: 50%;
overflow: hidden;
width: 220px;
height: 100%;
margin-top: -45px;
margin-left: -120px;
-webkit-transition: all 1s;
transition: all 1s;
-webkit-transform: translateY(15px);
transform: translateY(15px);
opacity: 0;
}
.meplayer-container.meplayer-isplaying .meplayer-lyric {
z-index: 0;
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
.meplayer-container .meplayer-lyric-area {
font-size: 12px;
margin-top: 35px;
-webkit-transition: -webkit-transform .7s;
transition: -webkit-transform .7s;
transition: transform .7s;
text-align: center;
opacity: 0;
color: var(--primary-text-color);
}
.meplayer-container .meplayer-lyric-area p {
line-height: 0;
width: 100%;
margin: 0;
padding: 0;
-webkit-transition: all .6s;
transition: all .6s;
opacity: 0;
}
.meplayer-container.meplayer-isplaying .meplayer-lyric-area p {
line-height: 20px;
}
.meplayer-container .meplayer-haslrc .meplayer-lyric-area {
display: block;
}
.meplayer-container.meplayer-isplaying .meplayer-lyric-area {
opacity: 1;
}
.meplayer-container .meplayer-lyric-area .meplayer-lyric-current {
font-size: 1.2em;
opacity: 1;
}
.meplayer-container .meplayer-lyric-area .meplayer-lyric-pre,
.meplayer-container .meplayer-lyric-area .meplayer-lyric-next {
opacity: .35;
}
.meplayer-container .meplayer-control {
position: relative;
float: right;
margin-right: 40px;
}
.meplayer-container .meplayer-volume-bg {
position: absolute;
z-index: -1;
width: 100%;
height: 100%;
-webkit-transition: all .8s;
transition: all .8s;
opacity: 0;
background: var(--panel-color);
}
.meplayer-container.meplayer-adjusting-volume .meplayer-volume-bg {
z-index: 20;
}
.meplayer-container .meplayer-volume {
font-size: 50px;
width: 60px;
margin: 13px auto 0;
-webkit-transition: all .9s;
transition: all .9s;
text-align: center;
color: var(--secondary-color);
}
.meplayer-container.meplayer-adjusting-volume .meplayer-volume-bg {
opacity: 1;
}
.meplayer-container .meplayer-volume-progress {
height: 4px;
-webkit-transition: width .2s;
transition: width .2s;
border-radius: 1px;
background: var(--secondary-color);
}
.meplayer-container .meplayer-control-play {
position: absolute;
top: -25px;
right: 0;
width: 50px;
height: 50px;
-webkit-transition: top .6s cubic-bezier(0, .74, .61, 1.35);
transition: top .6s cubic-bezier(0, .74, .61, 1.35);
cursor: pointer;
text-align: center;
color: var(--primary-color);
border-radius: 50%;
border: 1px var(--secondary-color) solid;
background: var(--panel-color);
box-shadow: 0 0 15px rgba(0, 0, 0, .2);
}
.meplayer-container .meplayer-control-play:hover {
-webkit-animation: breath 2s infinite alternate;
animation: breath 2s infinite alternate;
}
.meplayer-container.meplayer-isplaying .meplayer-control-play {
top: 20px;
-webkit-animation: breath 2s infinite alternate;
animation: breath 2s infinite alternate;
}
.meplayer-container .meplayer-control-play i {
line-height: 50px;
position: absolute;
left: 50%;
margin-left: -7px;
-webkit-transition: all .5s;
transition: all .5s;
}
.meplayer-container .meplayer-control-play .icon-play {
-webkit-transform: translateX(2px);
transform: translateX(2px);
opacity: 1;
}
.meplayer-container.meplayer-isplaying .meplayer-control-play .icon-play {
-webkit-transform: translateX(8px);
transform: translateX(8px);
opacity: 0;
}
.meplayer-container .meplayer-control-play .icon-pause {
-webkit-transform: translateX(-8px);
transform: translateX(-8px);
opacity: 0;
}
.meplayer-container.meplayer-isplaying .meplayer-control-play .icon-pause {
-webkit-transform: translateX(-1px);
transform: translateX(-1px);
opacity: 1;
}
.meplayer-container .meplayer-duration,
.meplayer-container .meplayer-loadingsign {
font-size: 12px;
position: absolute;
right: 40px;
bottom: 24px;
-webkit-transition: all .6s cubic-bezier(0, .74, .61, 1.35);
transition: all .6s cubic-bezier(0, .74, .61, 1.35);
letter-spacing: 1px;
color: var(--primary-text-color);
}
.meplayer-container.meplayer-isplaying .meplayer-duration,
.meplayer-container.meplayer-isplaying .meplayer-loadingsign {
z-index: -1;
bottom: 5px;
-webkit-transform: scale(.5, .5);
transform: scale(.5, .5);
opacity: 0;
}
.meplayer-container.meplayer-isloading .meplayer-duration {
opacity: 0;
}
.meplayer-container .meplayer-loadingsign {
opacity: 0;
}
.meplayer-container.meplayer-isloading .meplayer-loadingsign {
opacity: 1;
}
.meplayer-container .meplayer-duration i,
.meplayer-container .meplayer-loadingsign i {
margin-right: 3px;
-webkit-transition: all .7s;
transition: all .7s;
-webkit-transform: scale(.9, .9);
transform: scale(.9, .9);
color: var(--primary-color);
}
.meplayer-container.meplayer-isplaying .meplayer-duration i {
-webkit-transform: rotateZ(360deg);
transform: rotateZ(360deg);
}
.meplayer-container .meplayer-timeline-bg {
position: absolute;
bottom: 0;
width: 100%;
height: 8px;
}
.meplayer-container .meplayer-timeline {
position: absolute;
bottom: 0;
overflow: hidden;
width: 100%;
height: 3px;
-webkit-transition: all .5s;
transition: all .5s;
-webkit-transform: translateY(2px);
transform: translateY(2px);
opacity: 0;
background: var(--panel-color);
}
.meplayer-container.meplayer-isplaying .meplayer-timeline {
cursor: pointer;
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
.meplayer-container.meplayer-isplaying .meplayer-timeline-bg:hover .meplayer-timeline {
height: 8px;
}
.meplayer-container .meplayer-timeline .meplayer-timeline-passed {
position: absolute;
bottom: 0;
width: 0;
height: 100%;
background: var(--primary-color);
}
.meplayer-container.meplayer-changing-theme .meplayer-volume-bg {
display: none;
}
@-webkit-keyframes breath {
0% {
box-shadow: 0 0 35px rgba(0, 0, 0, .22);
}
100% {
box-shadow: 0 0 10px rgba(0, 0, 0, .33);
}
}
@keyframes breath {
0% {
box-shadow: 0 0 35px rgba(0, 0, 0, .22);
}
100% {
box-shadow: 0 0 10px rgba(0, 0, 0, .33);
}
}
.meplayer-container-mini {
position: relative;
width: 90px;
height: 90px;
border-radius: 50%;
background: var(--panel-color);
box-shadow: 0 0 20px rgba(0, 0, 0, .3);
}
.meplayer-isplaying.meplayer-container-mini {
-webkit-animation: breath 2s infinite alternate;
animation: breath 2s infinite alternate;
}
.meplayer-container-mini .meplayer-info, .meplayer-container-mini .meplayer-spectrum,
.meplayer-container-mini .meplayer-lyric, .meplayer-container-mini .meplayer-duration,
.meplayer-container-mini .meplayer-loadingsign, .meplayer-container-mini .meplayer-timeline-bg {
display: none;
}
.meplayer-container-mini .meplayer-control-play {
width: 90px;
height: 90px;
position: absolute;
top: 50%;
left: 50%;
font-size: 26px;
line-height: 90px;
margin-top: -45px;
margin-left: -45px;
color: var(--primary-color);
}
.meplayer-container-mini .meplayer-control-play [class^='icon-'] {
line-height: 90px;
position: absolute;
left: 50%;
margin-left: -11px;
-webkit-transition: all .5s;
transition: all .5s;
cursor: pointer;
}
.meplayer-container-mini .meplayer-control-play .icon-play {
-webkit-transform: translateX(4px);
transform: translateX(4px);
opacity: 1;
}
.meplayer-container-mini.meplayer-isplaying .meplayer-control-play .icon-play {
-webkit-transform: translateX(16px);
transform: translateX(16px);
opacity: 0;
}
.meplayer-container-mini .meplayer-control-play .icon-pause {
-webkit-transform: translateX(-16px);
transform: translateX(-16px);
opacity: 0;
}
.meplayer-container-mini.meplayer-isplaying .meplayer-control-play .icon-pause {
-webkit-transform: translateX(0);
transform: translateX(0);
opacity: 1;
}
.meplayer-container-mini .meplayer-volume-bg {
z-index: -1;
position: absolute;
width: 100%;
height: 100%;
font-size: 30px;
text-align: center;
line-height: 90px;
border-radius: 50%;
background: var(--panel-color);
color: var(--primary-text-color);
-webkit-transition: all 0.8s;
transition: all 0.8s;
}
.meplayer-container-mini.meplayer-adjusting-volume .meplayer-volume-bg {
opacity: 1;
z-index: 0;
}
.meplayer-container-mini.meplayer-adjusting-volume .meplayer-volume-bg i {
opacity: 1;
-webkit-transform: translateX(0px);
transform: translateX(0px);
}
.meplayer-container-mini .meplayer-volume-bg i {
-webkit-transition: all 0.7s;
transition: all 0.7s;
opacity: 0;
-webkit-transform: translateX(-20px);
transform: translateX(-20px);
}
.meplayer-container-mini.meplayer-changing-theme .meplayer-volume-bg {
display: none;
}
@-webkit-keyframes breath {
0% {
box-shadow: 0 0 35px rgba(0, 0, 0, .25);
}
100% {
box-shadow: 0 0 10px rgba(0, 0, 0, .33);
}
}
@keyframes breath {
0% {
box-shadow: 0 0 35px rgba(0, 0, 0, .25);
}
100% {
box-shadow: 0 0 10px rgba(0, 0, 0, .33);
}
}
.animate-spin {
-moz-animation: spin 2s infinite linear;
-o-animation: spin 2s infinite linear;
-webkit-animation: spin 2s infinite linear;
animation: spin 2s infinite linear;
display: inline-block;
}
@-moz-keyframes spin {
0% {
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-moz-transform: rotate(359deg);
-o-transform: rotate(359deg);
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@-webkit-keyframes spin {
0% {
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-moz-transform: rotate(359deg);
-o-transform: rotate(359deg);
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@-o-keyframes spin {
0% {
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-moz-transform: rotate(359deg);
-o-transform: rotate(359deg);
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@-ms-keyframes spin {
0% {
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-moz-transform: rotate(359deg);
-o-transform: rotate(359deg);
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes spin {
0% {
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-moz-transform: rotate(359deg);
-o-transform: rotate(359deg);
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
[class^="icon-"]:before, [class*=" icon-"]:before {
font-family: "fontello";
font-style: normal;
font-weight: normal;
speak: none;
display: inline-block;
text-decoration: inherit;
text-align: center;
font-variant: normal;
text-transform: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-play:before {
content: '\e801';
}
/* '' */
.icon-pause:before {
content: '\e802';
}
/* '' */
.icon-clock:before {
content: '\e803';
}
/* '' */
.icon-volume:before {
content: '\e804';
}
/* '' */
.icon-spin:before {
content: '\e800';
}

View File

@@ -0,0 +1,58 @@
.music-player-wrap {
padding: 0;
height: 90px;
position: fixed;
left: 50%;
bottom: 0;
transform: translateX(-50%);
}
.music-player {
width: 100%;
height: 90px;
}
.music-title {
color: var(--primary-color);
}
.music-item {
margin-top: 20px;
padding: 10px;
display: flex;
align-items: center;
color: var(--primary-text-color);
border: var(--secondary-text-color) 1px dashed;
border-radius: 4px;
}
.music-item:hover {
cursor: pointer;
border: var(--primary-color) 1px solid;
}
.music-cover {
width: 64px;
height: 64px;
object-fit: cover;
border-radius: 50%;
}
.music-info-wrap {
padding-left: 10px;
}
.music-name {
font-size: 18px;
font-weight: bolder;
}
.music-singer {
width: 200px;
font-size: 14px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
color: var(--secondary-text-color);
}

Binary file not shown.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Copyright (C) 2016 by original authors @ fontello.com</metadata>
<defs>
<font id="fontello" horiz-adv-x="1000" >
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
<missing-glyph horiz-adv-x="1000" />
<glyph glyph-name="spin6" unicode="&#xe800;" d="m855 9c-189-190-520-172-705 13-190 190-200 494-28 695 11 13 21 26 35 34 36 23 85 18 117-13 30-31 35-76 16-112-5-9-9-15-16-22-140-151-145-379-8-516 153-153 407-121 542 34 106 122 142 297 77 451-83 198-305 291-510 222l0 1c236 82 492-24 588-252 71-167 37-355-72-493-11-15-23-29-36-42z" horiz-adv-x="1000" />
<glyph glyph-name="play" unicode="&#xe801;" d="m772 333l-741-412q-13-7-22-2t-9 20v822q0 14 9 20t22-2l741-412q13-7 13-17t-13-17z" horiz-adv-x="785.7" />
<glyph glyph-name="pause" unicode="&#xe802;" d="m857 743v-786q0-14-10-25t-26-11h-285q-15 0-25 11t-11 25v786q0 14 11 25t25 11h285q15 0 26-11t10-25z m-500 0v-786q0-14-10-25t-26-11h-285q-15 0-25 11t-11 25v786q0 14 11 25t25 11h285q15 0 26-11t10-25z" horiz-adv-x="857.1" />
<glyph glyph-name="clock" unicode="&#xe803;" d="m0 350q0 95 37 182t100 149 150 100 182 37 182-37 149-100 100-149 37-182-37-182-100-150-149-100-182-37-182 37-150 100-100 150-37 182z m117 0q0-96 47-177t128-128 177-47q95 0 176 47t128 128 47 177q0 95-47 176t-128 128-176 47q-72 0-137-28t-112-75-75-112-28-136z m293 0v224q0 24 17 41t42 18 41-18 17-41v-200l142-141q17-17 17-42t-17-41-41-17q-25 0-42 17l-159 158q-1 2-4 5t-3 4q-1 2-2 4l-2 3t-1 4q-1 0-2 5-2 5-2 5-1 6-1 12z" horiz-adv-x="937.5" />
<glyph glyph-name="volume" unicode="&#xe804;" d="m0 142l0 416 236 0 354 289 0-994-354 289-236 0z m652 35q73 74 73 176t-73 178l71 74q105-106 107-254 0-145-107-246z m118-119q123 119 123 295t-123 299l76 74q154-154 154-372t-154-372z" horiz-adv-x="1000" />
</font>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

View File

@@ -30,6 +30,7 @@ function setTheme() {
root.style.setProperty("--secondary-text-color", `var(--${theme}-secondary-text-color)`);
root.style.setProperty("--background-color", `var(--${theme}-background-color)`);
root.style.setProperty("--panel-color", `var(--${theme}-panel-color)`);
const logo = document.querySelector(".main-logo-img")
if (logo !== null) {

View File

@@ -0,0 +1,660 @@
// webpackBootstrap
(function (modules) {
// The module cache
var installedModules = {};
// The require function
function __webpack_require__(moduleId) {
// Check if module is in cache
if (installedModules[moduleId]) return installedModules[moduleId].exports;
// Create a new module (and put it into the cache)
var module = installedModules[moduleId] = {
exports: {}, id: moduleId, loaded: false
};
// Execute the module function
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
// Flag the module as loaded
module.loaded = true;
// Return the exports of the module
return module.exports;
}
// expose the modules object (__webpack_modules__)
__webpack_require__.m = modules;
// expose the module cache
__webpack_require__.c = installedModules;
// __webpack_public_path__
__webpack_require__.p = "";
// Load entry module and return exports
return __webpack_require__(0);
})
([(function (module, exports, __webpack_require__) {
(function (global) {
'use strict';
var _slicedToArray = function () {
function sliceIterator(arr, i) {
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"]) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
return function (arr, i) {
if (Array.isArray(arr)) {
return arr;
} else if (Symbol.iterator in Object(arr)) {
return sliceIterator(arr, i);
} else {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
};
}();
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var _constants = __webpack_require__(1);
var _lyric = __webpack_require__(2);
var lyric = _interopRequireWildcard(_lyric);
var _utils = __webpack_require__(3);
var utils = _interopRequireWildcard(_utils);
var _spectrum = __webpack_require__(4);
var spectrum = _interopRequireWildcard(_spectrum);
var _selector = __webpack_require__(5);
var selector = _interopRequireWildcard(_selector);
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj;
} else {
var newObj = {};
if (obj != null) {
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key];
}
}
newObj.default = obj;
return newObj;
}
}
var root = (typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.window === window ? window : (typeof global === 'undefined' ? 'undefined' : _typeof(global)) === 'object' && global.global === global ? global : undefined;
root.MollyPlayer = function (options) {
// 检查必填选项
if (!(options.music && options.music.src)) {
console.error('未指定音乐地址');
return;
}
var musicConf = options.music, target = selector.$(options.target) || document.querySelector('.meplayer'),
theme = options.theme || _constants.THEME_DEFAULT, hasLrc = !!musicConf.lrc,
coverSrc = musicConf.cover || '../../../assets/img/music.png', loop = musicConf.loop || false,
autoplay = options.autoplay,
currentThemeClass = theme === _constants.THEME_DEFAULT ? 'meplayer-container' : 'meplayer-container-mini',
containerClass = currentThemeClass + ' ' + (hasLrc ? 'meplayer-haslrc' : '') + ' meplayer-isloading';
target.innerHTML = '<div class="' + containerClass + '">\n <audio src=' + musicConf.src + ' preload="auto"></audio>\n <div class="meplayer-info">\n <div class="meplayer-info-cover"><img src=' + coverSrc + ' alt="cd-cover"></div>\n <div class="meplayer-meta">\n <div class="meplayer-meta-title">' + musicConf.title + '</div>\n <div class="meplayer-meta-author">' + musicConf.author + '</div>\n <div class="meplayer-meta-time-tick"><span class="meplayer-meta-time-tick-text"></span></div>\n </div>\n </div>\n <canvas class="meplayer-spectrum"></canvas>\n <div class="meplayer-lyric"><div class="meplayer-lyric-area"></div></div>\n <div class="meplayer-control"><div class="meplayer-control-play"><i class="icon-play"></i><i class="icon-pause"></i></div></div>\n <div class="meplayer-volume-bg"><div class="meplayer-volume"><i class="icon-volume"></i><div class="meplayer-volume-progress"></div></div></div>\n <div class="meplayer-duration"><i class="icon-clock"></i><span class="meplayer-duration-text">loading</span></div>\n <div class="meplayer-loadingsign"><i class="icon-spin animate-spin"></i>loading</div>\n <div class="meplayer-timeline-bg"><div class="meplayer-timeline"><div class="meplayer-timeline-passed"></div></div></div>\n </div>';
var meplayerContainer = target.querySelector('.' + currentThemeClass),
_selector$init$select = selector.init(meplayerContainer).select(['audio', '.meplayer-control-play', '.meplayer-meta-time-tick-text', '.meplayer-duration', '.meplayer-timeline', '.meplayer-timeline-passed', '.meplayer-volume', '.meplayer-volume-progress', '.meplayer-lyric-area', '.meplayer-spectrum']),
_selector$init$select2 = _slicedToArray(_selector$init$select, 10), audio = _selector$init$select2[0],
playBtn = _selector$init$select2[1], timeTick = _selector$init$select2[2],
timeCount = _selector$init$select2[3], timeLine = _selector$init$select2[4],
timePassed = _selector$init$select2[5], volumeArea = _selector$init$select2[6],
volumeProgress = _selector$init$select2[7], lyricArea = _selector$init$select2[8],
canvas = _selector$init$select2[9], duration;
if (hasLrc) {
lyric.parse(musicConf.lrc).renderTo(lyricArea);
} else {
// 频谱动画初始化
spectrum.init(canvas);
}
eventInit();
if (autoplay) {
handlePlayClick();
}
// 重定义meplayer
root.mePlayer = {
play: play, pause: pause, toggleTheme: toggleTheme
// 给播放器绑定各种事件
};
function eventInit() {
audio.addEventListener('play', handleAudioStart);
audio.addEventListener('ended', handleAudioEnd);
audio.addEventListener('canplaythrough', handleCanPlayThrough);
audio.addEventListener('durationchange', handleDurationChange);
audio.addEventListener('timeupdate', handleTimeUpdate);
playBtn.addEventListener('click', handlePlayClick);
timeLine.addEventListener('click', handleTimeLineClick);
}
function handleAudioStart() {
utils.addClass(meplayerContainer, 'meplayer-isplaying');
}
function handleAudioEnd() {
if (loop) {
audio.play();
} else {
utils.removeClass(meplayerContainer, 'meplayer-isplaying');
}
}
function handleCanPlayThrough() {
duration = this.duration;
setTimeout(function () {
utils.removeClass(meplayerContainer, 'meplayer-isloading');
timeCount.querySelector('.meplayer-duration-text').innerText = utils.parseSec(duration.toFixed(0));
}, 1000);
}
function handleDurationChange() {
duration = this.duration;
}
function handleTimeUpdate() {
var curTime = audio.currentTime;
var curTimeForLrc = audio.currentTime.toFixed(3);
var playPercent = 100 * (curTime / duration);
timePassed.style.width = playPercent.toFixed(2) + '%';
timeTick.innerText = utils.parseSec(curTime);
if (hasLrc && theme === _constants.THEME_DEFAULT) {
var tempLrcIndex = lyric.currentIndex(curTimeForLrc);
var tempLrcLines = lyricArea.querySelectorAll('p');
var tempLrcLinePre = tempLrcLines[tempLrcIndex - 1];
var tempLrcLine = tempLrcLines[tempLrcIndex];
var tempLrcLineNext = tempLrcLines[tempLrcIndex + 1];
if (!tempLrcLine.className.includes('meplayer-lyric-current')) {
utils.removeClass(lyricArea.querySelector('.meplayer-lyric-current'), 'meplayer-lyric-current');
if (lyricArea.querySelector('.meplayer-lyric-pre')) {
utils.removeClass(lyricArea.querySelector('.meplayer-lyric-pre'), 'meplayer-lyric-pre');
}
if (lyricArea.querySelector('.meplayer-lyric-next')) {
utils.removeClass(lyricArea.querySelector('.meplayer-lyric-next'), 'meplayer-lyric-next');
}
utils.addClass(tempLrcLine, 'meplayer-lyric-current');
if (tempLrcLinePre) {
utils.addClass(tempLrcLinePre, 'meplayer-lyric-pre');
}
if (tempLrcLineNext) {
utils.addClass(tempLrcLineNext, 'meplayer-lyric-next');
}
lyricArea.style.webkitTransform = 'translateY(-' + tempLrcLines[tempLrcIndex].offsetTop + 'px)';
lyricArea.style.transform = 'translateY(-' + tempLrcLines[tempLrcIndex].offsetTop + 'px)';
}
}
}
function handlePlayClick() {
var _handleMouseWheel;
if (audio.paused) {
audio.play();
if (theme === _constants.THEME_DEFAULT && !hasLrc) {
spectrum.draw();
}
// 播放状态中可以用滑轮调节音量
meplayerContainer.addEventListener('mousewheel', function handleMouseWheel() {
var timer = null;
var step = 0.05;
_handleMouseWheel = function _handleMouseWheel(event) {
if (timer) {
clearTimeout(timer);
}
if (!meplayerContainer.className.includes('meplayer-adjusting-volume')) {
utils.addClass(meplayerContainer, 'meplayer-adjusting-volume');
}
if (event.wheelDeltaY < 0 && audio.volume > step) {
audio.volume -= step;
}
if (event.wheelDeltaY > 0 && audio.volume < 1 - step) {
audio.volume += step;
}
if (theme === _constants.THEME_DEFAULT) {
volumeProgress.style.width = audio.volume * 100 + '%';
} else {
volumeArea.querySelector('i').style.opacity = audio.volume;
}
event.preventDefault();
timer = setTimeout(function () {
utils.removeClass(meplayerContainer, 'meplayer-adjusting-volume');
}, 1000);
};
return _handleMouseWheel;
}());
} else {
audio.pause();
spectrum.stop();
meplayerContainer.removeEventListener('mousewheel', _handleMouseWheel);
}
utils.toggleClass(meplayerContainer, 'meplayer-isplaying');
}
function handleTimeLineClick(event) {
var rect = this.getBoundingClientRect();
var clickPosition = event.clientX - rect.left;
var clickPercent = clickPosition / rect.width;
timePassed.style.width = clickPercent * 100 + '%';
audio.currentTime = (clickPercent * duration).toFixed(0);
}
function play() {
if (audio.paused) {
audio.play();
}
}
function pause() {
if (!audio.paused) {
utils.removeClass(meplayerContainer, 'meplayer-isplaying');
audio.pause();
}
}
function toggleTheme() {
var step = 0.03;
var count = 0;
var maxCount = 200;
utils.addClass(meplayerContainer, 'meplayer-changing-theme');
theme = theme === _constants.THEME_DEFAULT ? _constants.THEME_MINI : _constants.THEME_DEFAULT;
loop();
function loop() {
count++;
meplayerContainer.style.opacity -= step;
if (meplayerContainer.style.opacity <= 0) {
step *= -1;
meplayerContainer.style.opacity = 0;
utils.toggleClass(meplayerContainer, 'meplayer-container-mini');
utils.toggleClass(meplayerContainer, 'meplayer-container');
}
if (meplayerContainer.style.opacity < 1 && count < maxCount) {
requestAnimationFrame(loop);
} else {
setTimeout(function () {
utils.removeClass(meplayerContainer, 'meplayer-changing-theme');
}, 500);
}
}
}
};
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
module.exports = root.mePlayer;
}
}.call(exports, (function () {
return this;
}())))
}),
(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var THEME_DEFAULT = 'default';
var THEME_MINI = 'mini';
var LYRIC_CURRENT_CLASS = 'meplayer-lyric-current';
var LYRIC_NEXT_CLASS = 'meplayer-lyric-next';
exports.THEME_DEFAULT = THEME_DEFAULT;
exports.THEME_MINI = THEME_MINI;
exports.LYRIC_CURRENT_CLASS = LYRIC_CURRENT_CLASS;
exports.LYRIC_NEXT_CLASS = LYRIC_NEXT_CLASS;
}),
(function (module, exports, __webpack_require__) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.currentIndex = exports.renderTo = exports.parse = undefined;
var _constants = __webpack_require__(1);
var lyrics;
// 歌词解析脚本
// 修改自https://github.com/DIYgod/APlayer
function parse(text) {
var lyric = text.split('\n');
var lrc = [];
var len = lyric.length;
var reg1 = /\[(\d{2}):(\d{2})\.(\d{2,3})]/g;
var reg2 = /\[(\d{2}):(\d{2})\.(\d{2,3})]/;
for (var i = 0; i < len; i++) {
var time = lyric[i].match(reg1);
var lrcText = lyric[i].replace(reg1, '').replace(/^\s+|\s+$/g, '');
// 排除空行
if (!lrcText) {
continue;
}
if (time != null) {
var timeLen = time.length;
for (var j = 0; j < timeLen; j++) {
var oneTime = reg2.exec(time[j]);
var lrcTime = oneTime[1] * 60 + parseInt(oneTime[2]) + parseInt(oneTime[3]) / ((oneTime[3] + '').length === 2 ? 100 : 1000);
lrc.push({
time: lrcTime, text: lrcText
});
}
}
}
lrc.sort(function (a, b) {
return a.time - b.time;
});
lyrics = lrc;
return this;
}
// 歌词文本解析成DOM结构
function renderTo(target) {
if (!lyrics) {
console.error('未指定歌词文本!');
return;
}
var lyricHTML = '';
for (var i = 0; i < lyrics.length; i++) {
lyricHTML += '<p>' + lyrics[i].text + '</p>';
}
target.innerHTML = lyricHTML;
target.querySelector('p').className = _constants.LYRIC_CURRENT_CLASS;
target.querySelector('p + p').className = _constants.LYRIC_NEXT_CLASS;
return this;
}
function currentIndex(time) {
if (time < lyrics[0].time) return 0;
for (var i = 0, l = lyrics.length; i < l; i++) {
if (time >= lyrics[i].time && (!lyrics[i + 1] || time <= lyrics[i + 1].time)) {
break;
}
}
return i;
}
exports.parse = parse;
exports.renderTo = renderTo;
exports.currentIndex = currentIndex;
}),
(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
function toggleClass(el, className) {
if (el.classList) {
el.classList.toggle(className);
} else {
var classes = el.className.split(' ');
var existingIndex = classes.indexOf(className);
if (existingIndex >= 0) classes.splice(existingIndex, 1); else classes.push(className);
el.className = classes.join(' ');
}
}
function addClass(el, className) {
if (el.classList) el.classList.add(className); else el.className += ' ' + className;
}
function removeClass(el, className) {
if (el.classList) el.classList.remove(className); else el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
}
function getAbsLeft(el) {
var left = el.offsetLeft;
while (el.offsetParent) {
el = el.offsetParent;
left += el.offsetLeft;
}
return left;
}
function parseSec(sec) {
var tempMin = sec / 60 | 0;
var tempSec = sec % 60 | 0;
var curMin = tempMin < 10 ? '0' + tempMin : tempMin;
var curSec = tempSec < 10 ? '0' + tempSec : tempSec;
return curMin + ':' + curSec;
}
exports.toggleClass = toggleClass;
exports.addClass = addClass;
exports.removeClass = removeClass;
exports.getAbsLeft = getAbsLeft;
exports.parseSec = parseSec;
}),
(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
/*
* 频谱动画模拟
* */
var canvas, ctx, specItems = [], needStop = false, timer = null, random = Math.random;
function randHeight() {
if (random() > 0.8) {
return random() * 8 + 11;
} else {
return random() * 6 + 2;
}
}
var randHeightGenerator = function randHeightGenerator(base) {
var max = base * 1.5 > 28 ? 28 : base * 1.5, min = 1, direction = random() > 0.5 ? 1 : -1,
tempHeight = base, curStep;
return function () {
curStep = direction;
tempHeight += curStep;
if (tempHeight >= max) {
direction *= -1;
tempHeight = max;
} else if (tempHeight <= min) {
direction *= -1;
tempHeight = min;
}
if (random() > 0.9) {
direction *= -1;
}
return tempHeight;
};
};
function loop() {
ctx.clearRect(0, -canvas.height / 2, canvas.width, canvas.height);
for (var i = 0; i < specItems.length; i++) {
var item = specItems[i];
var height = item.getHeight();
ctx.fillRect(i + specItems[i].xSpace, -height / 2, specItems[i].width, height);
}
if (!needStop) {
timer = requestAnimationFrame(loop);
}
}
function init(canvasElem) {
var width = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 220;
var height = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 30;
var color = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '#D94240';
canvas = canvasElem;
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext('2d');
ctx.fillStyle = color;
ctx.translate(0, height / 2);
for (var i = 0; i < 64; i++) {
var xSpace = i == 0 ? 0 : 5 * i;
var tempItem = {
xSpace: xSpace, width: 1, getHeight: randHeightGenerator(randHeight())
};
specItems.push(tempItem);
}
}
function draw() {
needStop = false;
loop();
}
function stop() {
needStop = true;
}
exports.init = init;
exports.draw = draw;
exports.stop = stop;
}),
(function (module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var container;
function init(element) {
container = $(element);
return this;
}
function select(element) {
var result;
if (Array.isArray(element)) {
var tempResults = [];
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = element[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var value = _step.value;
tempResults.push($(value, container));
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
result = tempResults;
} else {
result = $(element, container);
}
return result;
}
function $(element, context) {
var result;
context = context || document;
if (typeof element === 'string') {
result = context.querySelector(element);
} else if (element.toString().includes('HTMLDivElement')) {
result = element;
}
return result;
}
exports.init = init;
exports.select = select;
exports.$ = $;
})]);

View File

@@ -0,0 +1,33 @@
const bodyWrap = document.getElementById('body-wrap');
const playerWrap = document.getElementById('music-player-wrap');
syncWidth();
window.addEventListener('resize', syncWidth);
function syncWidth() {
playerWrap.style.width =window.getComputedStyle(bodyWrap).width;
}
function play(name, singer, coverSrc, musicSrc, lyricSrc) {
fetch(lyricSrc)
.then((res) => {
return res.text();
})
.then((data) => {
const musicData = musicSrc;
const lyricData = data;
MollyPlayer({
music: {
src: musicData,
lrc: lyricData,
cover: coverSrc,
title: name,
author: singer,
loop: true,
},
target: '#music-player',
autoplay: true,
});
});
}

View File

@@ -0,0 +1,93 @@
{{ define "music.html" }}
<html lang="{{ .site_info.language }}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ .site_info.title }}</title>
<link rel="icon" type="image/x-icon" href="../assets/img/logo.png"/>
<link rel="stylesheet" href="../assets/css/lib/fontawesome.all.min.css">
<link rel="stylesheet" href="../assets/css/lib/bootstrap.min.css">
<link rel="stylesheet" href="../assets/css/lib/meplayer.css">
<link rel="stylesheet" href="../assets/css/global.css">
<link rel="stylesheet" href="../assets/css/music.css">
<script src="../assets/js/lib/meplayer.js"></script>
<script src="../assets/js/lib/jquery.min.js"></script>
<script src="../assets/js/lib/bootstrap.min.js"></script>
<script src="../assets/js/lib/fontawesome.all.min.js"></script>
<!-- statistics script -->
{{ if .statistics.enable }}
{{ .statistics.script }}
{{ end }}
</head>
<body>
<div class="root-container">
<div class="d-block d-md-none" style="height: 30px;"></div>
<!-- menu -->
<div class="container p-3">
<div class="row pt-lg-3">
<div class="col mx-auto">
{{ range $i, $v := .menu.Items }}
<span class="main-menu-item">
<i class="{{ $v.Icon }} m-icon"></i>
<a class="main-menu-link" href="{{ $v.Url }}"> {{ $v.Name }} </a>
</span>
{{ end }}
</div>
</div>
</div>
<!-- body -->
<div class="container p-3" id="body-wrap">
<div class="row pt-lg-3">
<div class="col mx-auto">
<h3 class="music-title"># {{ .music.title }}</h3>
<div class="music-content">
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 row-cols-xl-4">
{{ range $i, $v := .music.list }}
<div class="col">
<div class="music-item" onclick="play('{{ $v.Name }}', '{{ $v.Singer }}', '{{ $v.Cover }}', '{{ $v.MusicUrl }}', '{{ $v.LyricUrl }}')">
<img class="music-cover" src="{{ $v.Cover }}">
<div class="music-info-wrap">
<div class="music-name">
{{ $v.Name }}
</div>
<div class="music-singer">
{{ $v.Singer }}
</div>
</div>
</div>
</div>
{{ end }}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- theme -->
<div class="theme-wrap" onclick="changeTheme()">
<svg t="1735089313984" class="icon theme-btn" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="6403" width="36" height="36">
<path d="M326.475761 829.999912l-36.600808 9.805927c-10.107989 2.709493-16.101899 13.097392-13.396433 23.201354 2.709493 10.107989 13.097392 16.101899 23.205381 13.395426l36.597787-9.80492c10.107989-2.709493 16.105926-13.097392 13.395426-23.205381C346.971649 833.288356 336.579722 827.290419 326.475761 829.999912L326.475761 829.999912zM371.675256 940.076204l-26.79186 26.795887c-7.402524 7.398496-7.402524 19.39437 0 26.787832 7.393462 7.402524 19.393363 7.402524 26.79186 0l26.79186-26.787832c7.398496-7.402524 7.398496-19.39437 0-26.795887C391.069627 932.681735 379.073752 932.681735 371.675256 940.076204L371.675256 940.076204zM734.141157 844.576399l-38.087958-9.83714c-10.512752-2.717548-21.325551 3.300527-24.144793 13.439729-2.816221 10.14323 3.425379 20.566369 13.942158 23.287945l38.08393 9.840161c10.517786 2.718555 21.329579-3.303547 24.149827-13.442749C750.900543 857.721114 744.657936 847.297974 734.141157 844.576399L734.141157 844.576399zM648.32142 945.201183c-7.701565-7.422661-20.184765-7.422661-27.882302 0-7.700558 7.425682-7.700558 19.460824 0 26.886506l27.882302 26.882478c7.69653 7.425682 20.180737 7.425682 27.881295 0 7.697537-7.425682 7.697537-19.456796 0-26.882478L648.32142 945.201183 648.32142 945.201183zM521.348807 948.22482c-10.461401 0-18.941278 8.479877-18.941278 18.942285l0 37.891618c0 10.461401 8.479877 18.941278 18.941278 18.941278 10.462408 0 18.946312-8.479877 18.946312-18.941278L540.29512 967.167104C540.29512 956.704696 531.811215 948.22482 521.348807 948.22482L521.348807 948.22482zM540.349491 492.068463c0.008055-0.200368 0.063433-0.380598 0.063433-0.581972L540.412924 33.50669c0-9.423316-8.479877-17.061448-18.942285-17.061448-10.461401 0-18.945305 7.638132-18.945305 17.061448l0 457.300163c-154.480359 5.447178-283.226073 143.101697-283.226073 305.561517l0 18.005894 151.931965 0c11.393765 64.408601 70.091387 113.669819 140.764747 113.669819 70.678394 0 129.379037-49.261217 140.773809-113.669819l151.930958 0 0-18.005894C804.70074 640.566995 686.30265 507.517909 540.349491 492.068463L540.349491 492.068463zM511.995973 892.037329c-50.606399 0-93.024913-33.238862-104.042108-77.663066l208.09227 0C605.029948 858.798467 562.611433 892.037329 511.995973 892.037329L511.995973 892.037329zM255.904095 778.366503c9.152467-138.251594 122.705489-251.815691 256.099932-251.815691 133.387395 0 246.93941 113.564097 256.091877 251.815691L255.904095 778.366503 255.904095 778.366503zM255.904095 778.366503"
fill="#6d6faa" p-id="6404"></path>
</svg>
</div>
<!-- music player -->
<div class="music-player-wrap" id="music-player-wrap">
<div class="music-player" id="music-player"></div>
</div>
<script src="../assets/js/global.js"></script>
<script src="../assets/js/music.js"></script>
</body>
</html>
{{ end }}