技术标签: 前端 html vue.js javascript
代码块中有注释 可以阅读一下 图片和音乐路径不同所以需要自己找一个合适的
播放模式支持:列表播放(默认)、循环播放、随机播放
能控制音量大小、上一曲、下一曲、暂停、播放、播放节奏状态、查看播放列表、删除某条单曲等……功能
顺便封装了个Message的消息提示 状态有(Success、Error、Warning、info)
<!DOCTYPE html>
<html lang="en">
<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>Music</title>
<style>
* {
box-sizing: border-box;
}
.music_image {
width: 55px;
height: 55px;
}
.music_content {
display: flex;
justify-content: space-between;
}
.music_title {
color: #333;
font-size: 14px;
font-weight: 600;
}
.music_duration {
font-size: 13px;
color: #999;
}
.music_button {
display: flex;
align-items: center;
margin: 0px 20px;
}
.duration_control {
width: 700px;
}
.music_vessel {
display: flex;
justify-content: center;
align-items: center;
padding: 10px 120px;
position: fixed;
left: 0;
bottom: 0;
width: 100%;
}
.music_up,
.music_play,
.music_pause,
.music_next {
margin: 0 8px;
background-size: 100% 100%;
width: 35px;
height: 35px;
cursor: pointer;
}
.music_up:hover,
.music_play:hover,
.music_pause:hover,
.music_next:hover {
opacity: .3;
}
.music_up {
background-image: url("./icon/up.png");
}
.music_play {
background-image: url("./icon/play.png");
}
.music_pause {
background-image: url("./icon/pause.png");
display: none;
}
.music_next {
background-image: url("./icon/next.png");
}
.music_audio {
display: none;
}
#range {
cursor: pointer;
}
.music_mode {
display: flex;
width: 100px;
justify-content: space-between;
margin: 0 20px;
position: relative;
}
.music_lists {
position: absolute;
right: 0;
width: 400px;
height: 0px;
bottom: 35px;
border-radius: 8px;
background-color: rgb(243, 243, 243);
z-index: 2;
display: none;
transition: all .3s;
overflow-y: scroll;
overflow-x: hidden;
padding: 10px;
}
/* .music_lists>div {
width: 100%;
height: 500px;
border: 1px solid #000;
} */
.music_lists>.lists {
width: 100%;
max-height: 300px;
min-height: 300px;
}
.music_lists>.info {
cursor: pointer;
padding: 10px;
margin-bottom: 5px;
display: flex;
justify-content: space-between;
font-size: 13px;
align-items: center;
border-radius: 5px;
}
.music_lists>.info:hover {
background-color: #fff;
}
.music_lists>.active {
font-weight: 600;
color: #149ce6;
background-color: #fff;
}
.music_lists>.info>.music_list_index {
margin-right: 10px;
}
.music_lists>.info>.music_list_title {
width: 90%;
}
.music_lists>.info>.music_list_delete {
width: 18px;
height: 18px;
background: url("icon/delete.png") no-repeat;
background-size: 100% 100%;
}
.music_lists>.info>.music_list_delete:hover {
opacity: 0.5;
}
.music_lists::-webkit-scrollbar {
width: 10px;
}
.music_lists::-webkit-scrollbar-thumb {
/*滚动条里面小方块*/
border-radius: 5px;
background: #b8b7b7;
}
.music_lists::-webkit-scrollbar-track {
/*滚动条里面轨道*/
border-radius: 10px;
background: transparent;
}
.volume_control {
position: absolute;
right: 17px;
bottom: 95px;
transform: rotate(-90deg);
background-color: rgb(243, 243, 243);
border-radius: 8px;
padding: 0 5px;
z-index: 1;
display: none;
}
.volume_range {
cursor: pointer;
}
.play_mode,
.music_list,
.volume {
width: 25px;
height: 25px;
background-size: 100% 100%;
cursor: pointer;
/* border:1px solid #000; */
}
.playing {
display: flex;
align-items: flex-end;
height: 10px;
}
.playing .side1,
.playing .side2,
.playing .side3 {
width: 2px;
background-color: #149ce6;
margin-left: 2px;
}
.playing .side1 {
height: 6px;
animation: playingSide1 1.2s linear infinite;
}
.playing .side2 {
height: 4px;
animation: playingSide2 1.2s linear infinite;
}
.playing .side3 {
height: 10px;
animation: playingSide3 1.2s linear infinite;
}
.play_mode {
background-image: url("icon/cycle.png");
}
.volume {
background-image: url("icon/volume.png");
}
.music_list {
background-image: url("icon/list.png");
background-size: 90% 90%;
background-repeat: no-repeat;
background-position: center bottom;
}
@keyframes musicListShow {
0% {
height: 0px;
display: none;
overflow-y: hidden;
}
100% {
height: 300px;
display: block;
overflow-y: hidden;
}
}
@keyframes musicListHidden {
0% {
height: 300px;
display: block;
}
100% {
height: 0px;
display: none;
}
}
@keyframes playingSide1 {
0% {
height: 6px;
}
56% {
height: 10px;
}
100% {
height: 8px;
}
}
@keyframes playingSide2 {
0% {
height: 4px;
}
28% {
height: 6px;
}
80% {
height: 12px;
}
100% {
height: 6px;
}
}
@keyframes playingSide3 {
0% {
height: 10px;
}
56% {
height: 8px;
}
100% {
height: 6px;
}
}
html,
body {
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
</head>
<body>
<div class="music_vessel">
<!-- 默认音乐图片填充 -->
<img src="./icon/music.png" class="music_image">
<!-- 操作按钮 -->
<div class="music_button">
<!-- 上一首 -->
<div class="music_up"></div>
<!-- 播放 -->
<div class="music_play"></div>
<!-- 暂停 -->
<div class="music_pause"></div>
<!-- 下一首 -->
<div class="music_next"></div>
</div>
<div class="music_info">
<!-- 显示时长 -->
<div class="music_content">
<span class="music_title">
你好世界,欢迎收听你的月亮我的心!
</span>
<span class="music_duration">
0:00 / 0:00
</span>
</div>
<!-- 时长控制 -->
<input type="range" id="range" class="duration_control" value="0" disabled>
</div>
<div class="music_mode">
<!-- 音量 -->
<div class="volume"></div>
<div class="volume_control">
<input type="range" class="volume_range" value="100" max="100">
</div>
<!-- 播放模式 -->
<div class="play_mode"></div>
<!-- 播放列表 -->
<div class="music_list"></div>
<div class="music_lists">
</div>
</div>
</div>
<audio src="" class="music_audio"></audio>
</body>
<script>
// 获取DOM元素
const $ = Dom => document.querySelector(Dom);
const class$ = Dom => document.querySelectorAll(Dom);
const volumeBtn = $(".volume"); //音量按钮
const musicListBtn = $(".music_list"); //列表按钮
const musicListsBox = $(".music_lists");//列表显示容器
const musicAudio = $(".music_audio"); //重中之重 音乐控件
const musicTitle = $(".music_title"); //音乐标题
const musicUp = $(".music_up"); // 上一首
const musicDuration = $(".music_duration"); // 时长显示
const durationControl = $(".duration_control"); //时长控制
const musicPlay = $(".music_play") // 播放
const musicPause = $(".music_pause")// 暂停
const musicNext = $(".music_next") // 下一首
let activePlay = -1; // 当前播放的那一首
let playModeStatus = "cycle"; //播放模式 (默认)cycle:列表循环 oneCycle:单曲循环 random:随机播放
const playModeStatusObj = {
cycle: "oneCycle",
oneCycle: "random",
random: "cycle",
}
const musicList = [
{ title: "万能青年旅店 - sha死那个石家庄人", url: "./audio/万能青年旅店 - sha死那个石家庄人.mp3" },
{ title: "隔壁老樊 - 姬和不如", url: "./audio/隔壁老樊 - 姬和不如.flac" },
{ title: "宋冬野 - 安和桥", url: "./audio/宋冬野 - 安和桥.flac" },
{ title: "宋冬野 - 董小姐", url: "./audio/宋冬野 - 董小姐.flac" },
{ title: "Ayo97 周思涵 - 感谢你曾来过", url: "./audio/Ayo97 周思涵 - 感谢你曾来过.mp3" },
{ title: "队长 - 哪里都是你", url: "./audio/队长 - 哪里都是你.flac" },
{ title: "C.HØPE - 沉沦与遐想", url: "./audio/C.HØPE - 沉沦与遐想.mp3" },
{ title: "Copy,BT07 - 晚风", url: "./audio/Copy,BT07 - 晚风.mp3" },
{ title: "Round_2 - Kill The Game", url: "./audio/Round_2 - Kill The Game.mp3" },
// { title: "艾福杰尼 - Yellow Skin Flow", url: "./audio/艾福杰尼 - Yellow Skin Flow.ape" },
{ title: "烟把儿乐队 - 纸短情长", url: "./audio/烟把儿乐队 - 纸短情长.mp3" },
{ title: "周杰伦 - 以父之名", url: "./audio/周杰伦 - 以父之名.flac" },
] //音乐播放列表
// 消息提醒
const message = (messageInfo) => {
let messageStatus = {
success: {
color: "#67C23A",
backgroundColor: "#F0F9EB"
},
warning: {
color: "#E6A23C",
backgroundColor: "#FDF6EC"
},
error: {
color: "#F56C6C",
backgroundColor: "#FEF0F0"
},
}
let messageDom = document.createElement("div");
let keepTime = messageInfo.keepTime || 1500
messageDom.innerText = messageInfo.message || ""
let messageStyle = {
color: "#909399",
backgroundColor: "#EDF2FC",
position: "fixed",
top: "-20%",
left: "50%",
transform: "translate(-50% , 0)",
width: "420px",
borderRadius: "5px",
boxSizing: "border-box",
padding: "15px 20px",
transition: "all 0.6s",
};
if (messageInfo.type) {
messageStyle.color = messageStatus[messageInfo.type].color;
messageStyle.backgroundColor = messageStatus[messageInfo.type].backgroundColor;
}
for (let styleKey in messageStyle) {
messageDom.style[styleKey] = messageStyle[styleKey];
}
document.body.appendChild(messageDom)
setTimeout(() => {
messageDom.style['top'] = "10%";
})
setTimeout(() => {
messageDom.style['top'] = "-20%"
setTimeout(() => {
messageDom.remove()
}, 600)
}, keepTime)
}
// 渲染播放列表
const createMusicList = () => {
let musicListHtml = "";
// <div class="music_list_index">${index + 1}< /div>
musicList.forEach((el, index) => {
musicListHtml += `
<div class="info ${activePlay == index ? 'active' : ''}" data-index="${index}">
<div class="music_list_index">
${activePlay == index ?
`<div class="playing">
<div class="side1"></div>
<div class="side2"></div>
<div class="side3"></div>
</div>`
: index + 1}
</div>
<div class="music_list_title">${el.title}</div>
<div class="music_list_delete" data-index="${index}"></div>
</div>`
})
musicListsBox.innerHTML = musicListHtml;
// 点击播放
class$(".info").forEach((dom_el) => {
dom_el.onclick = (e) => {
activePlay = dom_el.dataset['index'];
initialize();
}
})
//
class$(".music_list_delete").forEach((dom_el) => {
dom_el.onclick = (e) => {
e.stopPropagation();
musicList.splice(dom_el.dataset['index'], 1);
if (activePlay == dom_el.dataset['index']) {
activePlay--;
initialize();
}
createMusicList()
}
})
}
// 播放模式控制
$(".play_mode").onclick = (e) => {
playModeStatus = playModeStatusObj[playModeStatus];
$(".play_mode").style.backgroundImage = `url("icon/${playModeStatus}.png")`;
}
// 音量按钮
volumeBtn.onclick = (e) => {
$(".volume_control").style.display == "block" ? $(".volume_control").style.display = "none" : $(".volume_control").style.display = "block";
}
// 控制音量
$(".volume_control").children[0].onchange = (e) => {
musicAudio.volume = $(".volume_control").children[0].value / 100
}
// 列表点击事件
musicListBtn.onclick = (e) => {
musicListsBox.style.animation == "musicListShow .3s linear" ? musicListsBox.style.animation = "musicListHidden .3s linear" : musicListsBox.style.animation = "musicListShow .3s linear"
setTimeout(() => {
musicListsBox.style.display == 'block' ? (musicListsBox.style.display = "none") : (musicListsBox.style.display = "block")
}, 300)
musicListsBox.style.height == '300px' ? (musicListsBox.style.height = "0px") : (musicListsBox.style.height = "300px")
createMusicList()
}
//播放模式 (默认)cycle:列表循环 oneCycle:单曲循环 random:随机播放
// 上一首
musicUp.onclick = (e) => {
if (activePlay === 0 && playModeStatus != "random") {
message({ type: "warning", message: "已经是第一首了" })
return;
}
if (activePlay !== -1 && playModeStatus != "random") {
activePlay--;
}
if (playModeStatus == 'random') {
activePlay = Math.floor(Math.random() * 11);
}
initialize();
}
// 下一首
musicNext.onclick = (e) => {
if (musicList.length == 0) {
message({ type: "error", message: "播放列表中暂无歌曲" });
return;
}
if (activePlay == musicList.length - 1 && playModeStatus != "random") {
activePlay = 0;
initialize();
return;
}
if (activePlay !== -1 && playModeStatus != "random") {
activePlay++;
}
if (playModeStatus == 'random') {
activePlay = Math.floor(Math.random() * 11);
}
initialize();
}
// 渲染音频
const initialize = () => {
if (musicList.length == 0) {
message({ type: "error", message: "播放列表中暂无歌曲" });
musicTitle.innerText = "你好世界,欢迎收听你的月亮我的心!";
musicAudio.src = "";
durationControl.disabled = true;
durationControl.value = 0;
return;
}
if (activePlay === -1) {
activePlay = 0;
}
createMusicList()
musicTitle.innerText = musicList[activePlay].title;
musicAudio.src = musicList[activePlay].url;
durationControl.disabled = false;
musicAudio.play();
}
// 时长控制器状态值发生改变时
durationControl.onchange = (e) => {
musicAudio.currentTime = durationControl.value;
}
// 歌曲开始播放时
musicAudio.onplay = (e) => {
musicPlay.style.display = "none";
musicPause.style.display = "block";
[...$(".playing").children].forEach(el => el.style.animationPlayState = "")
}
// 歌曲暂停时
musicAudio.onpause = (e) => {
musicPlay.style.display = "block";
musicPause.style.display = "none";
[...$(".playing").children].forEach(el => el.style.animationPlayState = "paused")
}
// 歌曲播放结束时
musicAudio.onended = (e) => {
musicPlay.style.display = "block";
musicPause.style.display = "none";
if (playModeStatus == "oneCycle") {
musicAudio.play()
return;
}
if (activePlay == musicList.length - 1 && playModeStatus == "cycle") {
activePlay = 0;
initialize();
return;
}
if (activePlay != musicList.length - 1 && playModeStatus != "oneCycle") {
activePlay++;
}
if (playModeStatus == 'random') {
activePlay = Math.floor(Math.random() * 11);
}
initialize();
}
// 时长更改时会执行
musicAudio.ontimeupdate = (e) => {
if (musicAudio.currentTime >= 0 && musicAudio.duration >= 0) {
let totalF = parseInt(musicAudio.duration / 60); //总时长 分钟
let totalM = parseInt(musicAudio.duration % 60); //总时长 秒数
let currentF = parseInt(musicAudio.currentTime / 60);
let currentM = parseInt(musicAudio.currentTime % 60) < 10 ? '0' + parseInt(musicAudio.currentTime % 60) : parseInt(musicAudio.currentTime % 60);
musicDuration.innerHTML = ` ${currentF}:${currentM} / ${totalF}:${totalM}`;
durationControl.max = musicAudio.duration;
durationControl.value = musicAudio.currentTime;
}
}
// 开始播放
musicPlay.onclick = (e) => {
if (activePlay !== -1) {
musicAudio.play();
return;
}
initialize()
}
musicPause.onclick = (e) => {
musicAudio.pause();
}
</script>
</html>
如下图所示为笔者总结的java oop(面向对象)学习笔记,其中,附带有代码示例(未展开),方便理解记忆。需要源文件的请到我的资源中下载,下载地址:https://download.csdn.net/download/guaishounan/11292127 PS:下载需要积分,这是我这儿控制不了的,是平台设置的需要积分,并且积分会根据平台的算法动态增加或减少,我既然要分享,肯定是愿意零积分分...
1,使用composer在thinkphp5项目的根目录安装easywechat:composer require endroid/qrcode 安装endroid/qrcode$ composer require overtrue/wechat:~3.1 -vvv 2,安装好之后在控制器中开始使用,示例代码:① 配置,我这里的相关配置项是放在extra目录的wechat.php,内容如...
算法收敛性算法收敛性在迭代法中的一个概念。迭代是数值分析中通过从一个初始估计出发寻找一系列近似解来解决问题(一般是解方程或者方程组)的过程,为实现这一过程所使用的方法统称为迭代法(Iterative Method)。跟迭代法相对应的是直接法(或者称为一次解法),即一次性的快速解决问题,例如通过开方解决方程x+3= 4。一般如果可能,直接解法总是优先考虑的。但当遇到复杂问题时,特别是在未知量很...
一、QC介绍:QC的全称Quality center, 质量中心的意思,它是一款缺陷管理工具,可以组织和管理一个项目所有的测试阶段,如:从需求-用例编写-用例执行-提交缺陷-回归测试等。QC的背景:原属于Mercury公司,这是一家软件测试工具开发商,除了研发了QC之外,比较出名的工具有:LoadRunner----性能测试工具,QTP----自动化测试工具。后来Mercury公司被HP收...
在contos6上开发rails,我选择了vim。在安装rails.vim 的时候出现了一些问题,下面是汇总问题一: 找不到安装的地址。 安装rails.vim的时候一直找不到安装的路径和方法,在github上找到了方法:https://github.com/tpope/vim-rails#installation 在安装之前最好要先安装 pathogen.vim, 安装方法: h
If the exit status value (*note Program Termination::) of the childprocess is zero, then the status value reported by `waitpid' or `wait'is also zero. You can test for other kinds of information e
编译时不到conf.xml以及mapper.xml文件在使用Mybatis时,使用Maven clean后install后在target中找不到对应的两个xml文件。原因1:IDEA中你的文件创建时选择xml格式,但是后缀名没有xml,IDEA也会显示它是一个xml==但是并不会编译执行。==所以你需要将其重命名为conf.xml、mapper.xml。原因2:IDEA并不会编译java文件中的xml文件。我的文件目录为:对原因1的解决方法:将文件重命名,加上后缀.xml。对
(python3.6) [email protected]:~/project/mmdetection-master$ python tools/test.py configs/mask_rcnn/mask_rcnn_r50_fpn_1x_coco.py work_dirs/mask_rcnn_r50_fpn_1x_coco/epoch_12.pth --show-dir work_dirs/result --eval segmloading annotations into memory...Done (t=0.00s
狂神说SpringBoot系列连载课程,通俗易懂,基于SpringBoot2.2.5版本,欢迎各位狂粉转发关注学习。未经作者授权,禁止转载项目集成Swagger学习目标:了解Swagge...
软件安装及管理软件安装及管理知识要点软件的类型RPM软件包安装及管理Tar包安装、升级、卸载脚本安装、升级、卸载SRPM包安装软件类型软件是指计算机系统中的程序及其文档程序必须装入机器内部才能工作文档一般是给人看的,不一定装入机器软件是用户与硬件之间的接口界面系统软件(基础)和应用软件软件开发:程序开发:资料开发:测试应用程序...
原来父子 package的名字是 xxx-default ,结果一直无法拦截,最后去掉 - 就好了。。记录一下 父package<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.or
英文名称:Benzyl N-(4-Hydroxyphenyl)-carbamate中文名称:苄基 N-(4-羟基苯基)-氨基甲酸酯CAS No:7107-59-7分子式:C14H13NO3分子量:243.25纯 度:≥ 98%性 状:白色粉末结构式:相关产品:13100-46-4 1,2,3,4-四-O-乙酰基-β-D-吡喃葡萄糖6032-32-2 4-甲氧基苯基 β-D-吡喃葡萄糖苷72692-06-9 2,3,4-三-O...