audio标签
<audio src="images/myDream.m4a" id="audioInp" controls autoplay loop preload="metadata" />
标签的属性
各浏览器对不用音频格式的支持是不一样的
可以在audio标签用内部使用source来指定可以使用的音频源。
<audio src="images/myDream.m4a" id="audioInp" controls autoplay loop preload="metadata" />
<audio controls>
<source src="images/myDream.mp3" type="audio/mpeg" />
<source src="images/myDream.ogg" type="audio/ogg" />
<source src="images/myDream.wav" type="audio/wav" />
您的浏览器不支持Audio!
audio>
audio标签对应的DOM元素对象的常见属性
let audioInp = document.querySelector("#audioInp");
console.dir(audioInp)
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>audio音频处理title>
head>
<body>
<audio
src="https://zxt_team.gitee.io/opensource/qqmusic/mydream.m4a"
id="audioInp"
controls
autoplay
loop
preload="metadata"
/>
<script>
let audioInp = document.querySelector("#audioInp");
/*
currentTime:存储了当前播放的时间「单位秒」
duration:存储了总的时间
ended:true/false 是否播放完毕
paused:true/false 当前是否为暂停的
volume:0~1 控制音量的 1最大音量 0静音
play方法:控制音频播放
pause方法:控制播放暂停
canplay事件:音频可以播放了
canplaythrough事件:也是音频可以播放了(加载很多资源后,才会触发,保证音频播放中不卡顿)
pause事件
play事件
playing事件
volumechange事件
*/
script>
body>
html>
const obj = '要返回的数据';
const API = {
queryLyric() {
return new Promise((resolve) => {
setTimeout(() => {
resolve(obj);
}, Math.round(Math.random() * (2000 - 500) + 500));
});
},
};
const obj = {
code: 0,
message: "ok",
data: {
title: "我的梦 - 华为手机主题曲",
author: "张靓颖",
duration: "03:39",
pic: "https://zxt_team.gitee.io/opensource/qqmusic/mydream.jpg",
audio: "https://zxt_team.gitee.io/opensource/qqmusic/mydream.m4a",
lyric:
"[ti:《我的梦》]
[ar:张靓颖]
[al:]
[by:]
[offset:0]
[00:01.36]我的梦 (华为手机主题曲) - 张靓颖
[00:02.11]词:王海涛/张靓颖
[00:02.64]曲:Andy Love
[00:03.48]编曲:崔迪
[00:04.49]
[00:08.73]一直地一直地往前走
[00:11.65]
[00:13.02]疯狂的世界
[00:14.58]
[00:16.68]迎着痛把眼中所有梦
[00:20.52]
[00:21.03]都交给时间
[00:22.71]
[00:24.24]想飞就用心地去飞
[00:26.98]谁不经历狼狈
[00:30.68]
[00:31.60]我想我会忽略失望的灰
[00:34.99]拥抱遗憾的美
[00:39.05]我的梦说别停留等待
[00:43.94]就让光芒折射泪湿的瞳孔
[00:47.74]映出心中最想拥有的彩虹
[00:51.78]带我奔向那片有你的天空
[00:55.74]因为你是我的梦
[01:01.06]
[01:07.19]我的梦
[01:08.72]
[01:16.75]执着地勇敢地不回头
[01:20.29]
[01:21.05]穿过了黑夜踏过了边界
[01:24.87]路过雨路过风往前冲
[01:28.39]
[01:28.96]总会有一天站在你身边
[01:32.52]泪就让它往下坠
[01:35.00]溅起伤口的美
[01:38.60]
[01:39.55]哦别以为失去的最宝贵
[01:43.00]才让今天浪费
[01:47.04]我的梦说别停留等待
[01:51.93]就让光芒折射泪湿的瞳孔
[01:55.66]映出心中最想拥有的彩虹
[01:59.75]带我奔向那片有你的天空
[02:03.67]因为你是我的梦
[02:09.14]
[02:11.72]我的梦
[02:13.09]
[02:15.13]我的梦
[02:16.64]
[02:19.60]我的梦
[02:21.39]
[02:24.27]世界会怎么变化
[02:26.58]都不是意外
[02:28.33]记得用心去回答
[02:30.52]命运的精彩
[02:32.34]世界会怎么变化
[02:34.51]都离不开爱
[02:36.25]记得成长的对话
[02:38.28]
[02:39.11]勇敢地说我不再等待
[02:45.63]就让光芒折射泪湿的瞳孔
[02:49.75]映出心中最想拥有的彩虹
[02:53.74]带我奔向那片有你的天空
[02:57.73]因为你是我的梦
[03:02.71]
[03:05.51]我的梦
[03:07.32]
[03:09.20]我的梦
[03:14.12]因为你是我的梦",
},
};
const API = {
queryLyric() {
return new Promise((resolve) => {
setTimeout(() => {
resolve(obj);
}, Math.round(Math.random() * (2000 - 500) + 500));
});
},
};
let lyric = "[ti:《我的梦》]
[ar:张靓颖]
[al:]
[by:]
[offset:0]
[00:01.36]我的梦 (华为手机主题曲) - 张靓颖
[00:02.11]词:王海涛/张靓颖
[00:02.64]曲:Andy Love
[00:03.48]编曲:崔迪
[00:04.49]
[00:08.73]一直地一直地往前走
[00:11.65]
[00:13.02]疯狂的世界
[00:14.58]
[00:16.68]迎着痛把眼中所有梦
[00:20.52]
[00:21.03]都交给时间
[00:22.71]
[00:24.24]想飞就用心地去飞
[00:26.98]谁不经历狼狈
[00:30.68]
[00:31.60]我想我会忽略失望的灰
[00:34.99]拥抱遗憾的美
[00:39.05]我的梦说别停留等待
[00:43.94]就让光芒折射泪湿的瞳孔
[00:47.74]映出心中最想拥有的彩虹
[00:51.78]带我奔向那片有你的天空
[00:55.74]因为你是我的梦
[01:01.06]
[01:07.19]我的梦
[01:08.72]
[01:16.75]执着地勇敢地不回头
[01:20.29]
[01:21.05]穿过了黑夜踏过了边界
[01:24.87]路过雨路过风往前冲
[01:28.39]
[01:28.96]总会有一天站在你身边
[01:32.52]泪就让它往下坠
[01:35.00]溅起伤口的美
[01:38.60]
[01:39.55]哦别以为失去的最宝贵
[01:43.00]才让今天浪费
[01:47.04]我的梦说别停留等待
[01:51.93]就让光芒折射泪湿的瞳孔
[01:55.66]映出心中最想拥有的彩虹
[01:59.75]带我奔向那片有你的天空
[02:03.67]因为你是我的梦
[02:09.14]
[02:11.72]我的梦
[02:13.09]
[02:15.13]我的梦
[02:16.64]
[02:19.60]我的梦
[02:21.39]
[02:24.27]世界会怎么变化
[02:26.58]都不是意外
[02:28.33]记得用心去回答
[02:30.52]命运的精彩
[02:32.34]世界会怎么变化
[02:34.51]都离不开爱
[02:36.25]记得成长的对话
[02:38.28]
[02:39.11]勇敢地说我不再等待
[02:45.63]就让光芒折射泪湿的瞳孔
[02:49.75]映出心中最想拥有的彩虹
[02:53.74]带我奔向那片有你的天空
[02:57.73]因为你是我的梦
[03:02.71]
[03:05.51]我的梦
[03:07.32]
[03:09.20]我的梦
[03:14.12]因为你是我的梦"
// 1. 歌词解析:
// [ti:《我的梦》]
// [ar:张靓颖]
// [al:]
// [by:]
// [offset:0]
// [00:01.36]我的梦 (华为手机主题曲) - 张靓颖
// [00:02.11]词:王海涛/张靓颖
// [00:02.64]曲:Andy Love
// [00:03.48]编曲:崔迪
// [00:04.49]
// [00:08.73]一直地一直地往前走
// ...
// [03:14.12]因为你是我的梦
// 2. 歌词内容推测:
// ->空格
// ( ->(
// ) ->)
// - ->-
//
->换行符
// : ->前面的数字是分钟
// . ->前面的数字是秒
// 3. 得到歌词的内容格式。
// 一行歌词:[分钟数:秒数.毫秒数]内部有特殊字符的歌词内容
// 内部有特殊字符的歌词内容:` 为 空格` `( 为 (` `) 为 )` `- 为 -` 。
/* lyric.replace(
/\[(\d+):(\d+).(?:\d+)\]([^?]+)(?:
)?/g,
(_, $1, $2, $3) => {
console.log($1, $2, $3);
}
); */
// 处理歌词部分的特殊符号
lyric = lyric.replace(/(\d+);/g, (value, $1) => {
let instead = value;
switch (+$1) {
case 32:
instead = " ";
break;
case 40:
instead = "(";
break;
case 41:
instead = ")";
break;
case 45:
instead = "-";
break;
default:
}
return instead;
});
// 解析歌词信息
let arr = [];
lyric.replace(
/\[(\d+):(\d+).(?:\d+)\]([^?]+)(?:
)?/g,
(_, $1, $2, $3) => {
arr.push({
minutes: $1,
seconds: $2,
text: $3,
});
}
);
console.log(arr,lyric)
JS高级进阶/day0619_QQMusic/index.html
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
/>
<title>QQ音乐播放器title>
<link rel="stylesheet" href="css/index.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js" async>script>
head>
<body>
<div id="app">
<header class="header-box">
<div class="base">
div>
<a href="javascript:;" class="player-button">a>
header>
<main class="main-box">
<div class="wrapper">
div>
main>
<footer class="footer-box">
<div class="bar">
<span class="time current">00:00span>
<div class="progress">
<div class="already">div>
div>
<span class="time duration">00:00span>
div>
<a href="#" class="download">下载这首音乐a>
footer>
<div class="mark-image">div>
<div class="mark-overlay">div>
<div class="loading-box">
<div class="content">
<img src="images/loading.gif" alt="" />
<span>奴家正在努力加载中...span>
div>
div>
<audio src="" id="audioBox" preload="metadata">audio>
div>
<script>
(function () {
const app = document.querySelector("#app"),
HTML = document.documentElement;
const computed = function computed() {
let orien = Math.abs(window.orientation);
if (orien === 90) {
// 切换到横屏
alert("横屏体验不佳,请您切换到竖屏");
app.style.display = "none";
return;
}
// 当前是竖屏
app.style.display = "block";
// 计算REM的换算比例
let deviceW = HTML.clientWidth,
designW = 375,
initialRatio = 100;
if (deviceW > 540) deviceW = 540;
let currentRatio = (deviceW / designW) * initialRatio;
HTML.style.fontSize = currentRatio + "px";
};
computed();
window.addEventListener("resize", computed);
// 基于 resize 代替 orientationchange 事件:这样可以适配模拟器中,设备的切换场景
})();
script>
<script src="js/api.js">script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/fastclick.min.js">script>
<script src="js/index.js">script>
body>
html>
JS高级进阶/day0619_QQMusic/css/index.css
由less文件编译而来
html {
font-size: 100px;
}
html,
body,
#app {
height: 100%;
overflow: hidden;
}
#app {
position: relative;
margin: 0 auto;
max-width: 540px;
font-size: 0.14rem;
}
.header-box,
.footer-box,
.main-box {
box-sizing: border-box;
height: 1rem;
overflow: hidden;
}
.main-box {
height: calc(100vh - 2rem);
}
/* 通用样式 */
.text-clip {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
/* Loading层 */
.loading-box {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
box-sizing: border-box;
width: 100vw;
height: 100vh;
background: #555;
display: flex;
justify-content: center;
align-items: center;
}
.loading-box .content img,
.loading-box .content span {
display: block;
}
.loading-box .content img {
margin: 0 auto;
width: 0.5rem;
height: 0.5rem;
}
.loading-box .content span {
margin-top: 0.1rem;
color: #1989fa;
}
/* 背景层 */
.mark-overlay,
.mark-image {
position: absolute;
top: -10%;
left: -10%;
width: 120%;
height: 120%;
}
.mark-image {
z-index: -2;
background-repeat: no-repeat;
background-size: cover;
filter: blur(6px);
}
.mark-overlay {
z-index: -1;
background: rgba(0, 0, 0, 0.5);
}
/* 头部区域样式 */
.header-box {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.15rem;
}
.header-box .player-button {
margin-left: 0.05rem;
width: 0.35rem;
height: 0.35rem;
background: url('../images/music.svg') no-repeat;
background-size: 100% 100%;
}
.header-box .player-button.move {
animation: musicMove 1s linear 0s infinite both;
}
.header-box .base {
flex-grow: 1;
display: flex;
}
.header-box .base .cover {
width: 0.7rem;
height: 0.7rem;
background: #AAA;
}
.header-box .base .cover img {
display: block;
width: 100%;
height: 100%;
}
.header-box .base .cover img[src=""] {
display: none;
}
.header-box .base .info {
flex-grow: 1;
margin-left: 0.05rem;
max-width: 2.3rem;
}
.header-box .base .info .title,
.header-box .base .info .author {
line-height: 0.35rem;
color: #fff;
font-size: 0.17rem;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.header-box .base .info .author {
font-size: 0.15rem;
}
@keyframes musicMove {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* 歌词区域样式 */
.main-box .wrapper {
transform: translateY(0);
transition: transform 0.3s;
}
.main-box .wrapper p {
height: 0.5rem;
line-height: 0.5rem;
text-align: center;
font-size: 0.15rem;
color: rgba(255, 255, 255, 0.5);
}
.main-box .wrapper p.active {
color: #31C27C;
transition: color 0.3s;
}
/* 尾部区域样式 */
.footer-box {
padding: 0 0.1rem;
}
.footer-box .download {
display: block;
margin: 0 auto;
width: 2.13rem;
height: 0.5rem;
line-height: 0.5rem;
text-align: center;
font-size: 0.18rem;
color: #fff;
text-indent: 0.2rem;
border-radius: 0.25rem;
background: url('../images/sprite_play.png') no-repeat #31C27C;
background-size: 0.4rem 3.5rem;
background-position: 0.1rem -2.915rem;
}
.footer-box .bar {
display: flex;
align-items: center;
}
.footer-box .bar .time {
width: 0.4rem;
line-height: 0.46rem;
text-align: center;
font-size: 0.12rem;
color: rgba(255, 255, 255, 0.5);
}
.footer-box .bar .progress {
position: relative;
flex-grow: 1;
height: 0.02rem;
background: rgba(255, 255, 255, 0.5);
}
.footer-box .bar .progress .already {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 100%;
background: #31C27C;
}
/* 音频 */
#audioBox {
display: none;
}
JS高级进阶/day0619_QQMusic/css/index.less
html {
font-size: 100px; //1REM=100PX「在375px的设计稿中」
}
html,
body,
#app {
height: 100%;
overflow: hidden;
}
#app {
position: relative;
margin: 0 auto;
max-width: 540px;
font-size: .14rem;
}
.header-box,
.footer-box,
.main-box {
box-sizing: border-box;
height: 1rem;
overflow: hidden;
}
.main-box {
height: calc(100vh - 2rem);
}
/* 通用样式 */
@com-green: #31C27C;
@com-gray: rgba(255, 255, 255, .5);
.text-clip {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
/* Loading层 */
.loading-box {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
box-sizing: border-box;
width: 100vw;
height: 100vh;
background: #555;
display: flex;
justify-content: center;
align-items: center;
.content {
img,
span {
display: block;
}
img {
margin: 0 auto;
width: .5rem;
height: .5rem;
}
span {
margin-top: .1rem;
color: rgb(25, 137, 250);
}
}
}
/* 背景层 */
.mark-overlay,
.mark-image {
position: absolute;
top: -10%;
left: -10%;
width: 120%;
height: 120%;
}
.mark-image {
z-index: -2;
background-repeat: no-repeat;
background-size: cover;
filter: blur(6px); // 设置模糊度
}
.mark-overlay {
z-index: -1;
background: rgba(0, 0, 0, .5);
}
/* 头部区域样式 */
.header-box {
display: flex;
justify-content: space-between;
align-items: center;
padding: .15rem;
.player-button {
margin-left: .05rem;
width: .35rem;
height: .35rem;
background: url('../images/music.svg') no-repeat;
background-size: 100% 100%;
&.move {
animation: musicMove 1s linear 0s infinite both;
}
}
.base {
flex-grow: 1;
display: flex;
.cover {
width: .7rem;
height: .7rem;
background: #AAA;
img {
display: block;
width: 100%;
height: 100%;
}
img[src=""] {
display: none;
}
}
.info {
flex-grow: 1;
margin-left: .05rem;
max-width: 2.3rem;
.title,
.author {
line-height: .35rem;
color: #fff;
font-size: .17rem;
.text-clip;
}
.author {
font-size: .15rem;
}
}
}
}
@keyframes musicMove {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* 歌词区域样式 */
.main-box {
.wrapper {
transform: translateY(0);
transition: transform .3s;
p {
height: .5rem;
line-height: .5rem;
text-align: center;
font-size: .15rem;
color: @com-gray;
&.active {
color: @com-green;
transition: color .3s;
}
}
}
}
/* 尾部区域样式 */
.footer-box {
padding: 0 .1rem;
.download {
display: block;
margin: 0 auto;
width: 2.13rem;
height: .5rem;
line-height: .5rem;
text-align: center;
font-size: .18rem;
color: #fff;
text-indent: .2rem;
border-radius: .25rem;
background: url('../images/sprite_play.png') no-repeat @com-green;
background-size: .4rem 3.5rem;
background-position: .1rem -2.915rem;
}
.bar {
display: flex;
align-items: center;
.time {
width: .4rem;
line-height: .46rem;
text-align: center;
font-size: .12rem;
color: @com-gray;
}
.progress {
position: relative;
flex-grow: 1;
height: .02rem;
background: @com-gray;
.already {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 100%;
background: @com-green;
}
}
}
}
/* 音频 */
#audioBox {
display: none;
}
JS高级进阶/day0619_QQMusic/js/api.js
const obj = {
code: 0,
message: "ok",
data: {
title: "我的梦 - 华为手机主题曲",
author: "张靓颖",
duration: "03:39",
pic: "https://zxt_team.gitee.io/opensource/qqmusic/mydream.jpg",
audio: "https://zxt_team.gitee.io/opensource/qqmusic/mydream.m4a",
lyric:
"[ti:《我的梦》]
[ar:张靓颖]
[al:]
[by:]
[offset:0]
[00:01.36]我的梦 (华为手机主题曲) - 张靓颖
[00:02.11]词:王海涛/张靓颖
[00:02.64]曲:Andy Love
[00:03.48]编曲:崔迪
[00:04.49]
[00:08.73]一直地一直地往前走
[00:11.65]
[00:13.02]疯狂的世界
[00:14.58]
[00:16.68]迎着痛把眼中所有梦
[00:20.52]
[00:21.03]都交给时间
[00:22.71]
[00:24.24]想飞就用心地去飞
[00:26.98]谁不经历狼狈
[00:30.68]
[00:31.60]我想我会忽略失望的灰
[00:34.99]拥抱遗憾的美
[00:39.05]我的梦说别停留等待
[00:43.94]就让光芒折射泪湿的瞳孔
[00:47.74]映出心中最想拥有的彩虹
[00:51.78]带我奔向那片有你的天空
[00:55.74]因为你是我的梦
[01:01.06]
[01:07.19]我的梦
[01:08.72]
[01:16.75]执着地勇敢地不回头
[01:20.29]
[01:21.05]穿过了黑夜踏过了边界
[01:24.87]路过雨路过风往前冲
[01:28.39]
[01:28.96]总会有一天站在你身边
[01:32.52]泪就让它往下坠
[01:35.00]溅起伤口的美
[01:38.60]
[01:39.55]哦别以为失去的最宝贵
[01:43.00]才让今天浪费
[01:47.04]我的梦说别停留等待
[01:51.93]就让光芒折射泪湿的瞳孔
[01:55.66]映出心中最想拥有的彩虹
[01:59.75]带我奔向那片有你的天空
[02:03.67]因为你是我的梦
[02:09.14]
[02:11.72]我的梦
[02:13.09]
[02:15.13]我的梦
[02:16.64]
[02:19.60]我的梦
[02:21.39]
[02:24.27]世界会怎么变化
[02:26.58]都不是意外
[02:28.33]记得用心去回答
[02:30.52]命运的精彩
[02:32.34]世界会怎么变化
[02:34.51]都离不开爱
[02:36.25]记得成长的对话
[02:38.28]
[02:39.11]勇敢地说我不再等待
[02:45.63]就让光芒折射泪湿的瞳孔
[02:49.75]映出心中最想拥有的彩虹
[02:53.74]带我奔向那片有你的天空
[02:57.73]因为你是我的梦
[03:02.71]
[03:05.51]我的梦
[03:07.32]
[03:09.20]我的梦
[03:14.12]因为你是我的梦",
},
};
const API = {
queryLyric() {
return new Promise((resolve) => {
setTimeout(() => {
resolve(obj);
}, Math.round(Math.random() * (2000 - 500) + 500));
});
},
};
JS高级进阶/day0619_QQMusic/js/index.js
// 解决 click 事件的300ms延迟问题
FastClick.attach(document.body);
console.log(`cdn-->`);
(async function () {
const baseBox = document.querySelector(".header-box .base"),
playerButton = document.querySelector(".player-button"),
wrapperBox = document.querySelector(".wrapper"),
footerBox = document.querySelector(".footer-box"),
currentBox = footerBox.querySelector(".current"),
durationBox = footerBox.querySelector(".duration"),
alreadyBox = footerBox.querySelector(".already"),
markImageBox = document.querySelector(".mark-image"),
loadingBox = document.querySelector(".loading-box"),
audioBox = document.querySelector("#audioBox");
let wrapperList = [],
timer = null,
matchNum = 0; //记录历史匹配的数量
/* 音乐控制 */
const format = function format(time) {
let minutes = Math.floor(time / 60),
seconds = Math.round(time - minutes * 60);
minutes = minutes < 10 ? "0" + minutes : "" + minutes;
seconds = seconds < 10 ? "0" + seconds : "" + seconds;
return {
minutes,
seconds,
};
};
const playend = function playend() {
clearInterval(timer);
timer = null;
currentBox.innerHTML = "00:00";
alreadyBox.style.width = "0%";
wrapperBox.style.transform = "translateY(0)";
wrapperList.forEach((item) => (item.className = ""));
matchNum = 0;
playerButton.className = "player-button";
};
const handle = function handle() {
let pH = wrapperList[0].offsetHeight;
let { currentTime, duration } = audioBox;
if (isNaN(currentTime) || isNaN(duration)) return;
// 播放结束
if (currentTime >= duration) {
playend();
return;
}
// 控制进度条
let { minutes: currentTimeMinutes, seconds: currentTimeSeconds } =
format(currentTime),
{ minutes: durationMinutes, seconds: durationSeconds } = format(duration),
ratio = Math.round((currentTime / duration) * 100);
currentBox.innerHTML = `${currentTimeMinutes}:${currentTimeSeconds}`;
durationBox.innerHTML = `${durationMinutes}:${durationSeconds}`;
alreadyBox.style.width = `${ratio}%`;
// 控制歌词:查找和当前播放时间匹配的歌词段落
let matchs = wrapperList.filter((item) => {
let minutes = item.getAttribute("minutes"),
seconds = item.getAttribute("seconds");
return minutes === currentTimeMinutes && seconds === currentTimeSeconds;
});
if (matchs.length > 0) {
// 让匹配的段落有选中样式,而其余的移除选中样式
wrapperList.forEach((item) => (item.className = ""));
matchs.forEach((item) => (item.className = "active"));
// 控制移动
matchNum += matchs.length;
if (matchNum > 3) {
let offset = (matchNum - 3) * pH;
wrapperBox.style.transform = `translateY(${-offset}px)`;
}
}
};
playerButton.addEventListener("click", function () {
if (audioBox.paused) {
// 当前是暂停的:我们让其播放
audioBox.play();
playerButton.className = "player-button move";
handle();
if (!timer) timer = setInterval(handle, 1000);
return;
}
// 当前是播放的:我们让其暂停
audioBox.pause();
playerButton.className = "player-button";
clearInterval(timer);
timer = null;
});
/* 绑定数据 */
const bindLyric = function bindLyric(lyric) {
// 处理歌词部分的特殊符号
lyric = lyric.replace(/(\d+);/g, (value, $1) => {
let instead = value;
switch (+$1) {
case 32:
instead = " ";
break;
case 40:
instead = "(";
break;
case 41:
instead = ")";
break;
case 45:
instead = "-";
break;
default:
}
return instead;
});
// 解析歌词信息
let arr = [];
lyric.replace(
/\[(\d+):(\d+).(?:\d+)\]([^?]+)(?:
)?/g,
(_, $1, $2, $3) => {
arr.push({
minutes: $1,
seconds: $2,
text: $3,
});
}
);
// 歌词绑定
let str = ``;
arr.forEach(({ minutes, seconds, text }) => {
str += `${minutes}
" seconds="${seconds}">
${text}
`;
});
wrapperBox.innerHTML = str;
// 获取所有的P标签
wrapperList = Array.from(wrapperBox.querySelectorAll("p"));
};
const binding = function binding(data) {
let { title, author, duration, pic, audio, lyric } = data;
// @1 绑定头部基本信息
baseBox.innerHTML = `
${pic}" alt="">
${title}
${author}
`;
// @2 杂七杂八的信息
durationBox.innerHTML = duration;
markImageBox.style.backgroundImage = `url(${pic})`;
audioBox.src = audio;
// @3 绑定歌词信息
bindLyric(lyric);
// @4 关闭Loading效果
loadingBox.style.display = "none";
};
/* 向服务器发送请求,从服务器获取相关的数据 */
try {
let { code, data } = await API.queryLyric();
if (+code === 0) {
// 请求成功:网络层和业务层都成功
binding(data);
return;
}
} catch (_) {}
// 请求失败
alert("网络繁忙,请刷新页面");
})();
组件化开发:
脚手架:把webpack相关的配置规则都处理好了,把一个工程化组件化的项目架子都搭建完毕了