1、进度条的用的是vant的Progress组件,比手写进度条方便很多,有自带的事件

2、H5页面兼容pc

效果展示

上代码

一、template模块

<template lang="pug">
.audioPlay
main
.audioBox
.imgBox
van-image.songImg(
width="4.6rem",
height="4.6rem",
fit="cover",
style="border-radius: 5px; overflow: hidden",
:src="require('@/assets/images/media/song.png')"
)
.titBox 文稿
.titText {{ title }}
.audioControl
audio(
:src="audioSrc",
@canplay="getDuration",
@timeupdate="updateTime",
v-show="false",
controls,
ref="audio"
)
van-slider.audioSlider(
v-model="sliderValue",
@update:model-value="sliderOnChange",
active-color="#D8BE98",
inactive-color="#E0E0E0",
:disabled="isSlide > 0 ? false : true"
)
template(#button)
.custom-button {{ currentDuration }}/{{ duration }}
ul.handleUl
li.handleLi(@click="handleBack")
van-image.handleImg(
width="0.44rem",
height="0.44rem",
fit="cover",
:src="require('@/assets/images/media/houtui.png')"
)
li.handleLi(@click="prevPlay(isPlayNum)")
van-image.handleImg(
width="0.44rem",
height="0.44rem",
fit="cover",
:src="isPlayNum > 1 ? require('@/assets/images/media/prevL.png') : require('@/assets/images/media/prev.png')"
)
li.handleLi(@click="handlePauseOrPlay")
van-image.handleImg(
width="0.98rem",
height="0.98rem",
fit="cover",
:src="paused ? require('@/assets/images/media/play.png') : require('@/assets/images/media/stop.png')"
)
li.handleLi(@click="nextPlay(isPlayNum)")
van-image.handleImg(
width="0.44rem",
height="0.44rem",
fit="cover",
:src="isPlayNum < catalogArray.length ? require('@/assets/images/media/nextL.png') : require('@/assets/images/media/next.png')"
)
li.handleLi(@click="handleForward")
van-image.handleImg(
width="0.44rem",
height="0.44rem",
fit="cover",
:src="require('@/assets/images/media/qianjin.png')"
)
ul.funUl
li.funLi(@click="sheetShowCli('mulu', '选集')")
van-image.funImg(
width="0.54rem",
height="0.54rem",
fit="cover",
:src="require('@/assets/images/media/mulu.png')"
)
p.funtext 目录
li.funLi(@click="sheetShowCli('beisu', '倍速')")
van-image.funImg(
width="0.54rem",
height="0.54rem",
fit="cover",
:src="require('@/assets/images/media/beisu.png')"
)
p.funtext 倍速
li.funLi(
@click="sheetShowCli('pinglun', '评论')"
)
van-image.funImg(
width="0.54rem",
height="0.54rem",
fit="cover",
:src="require('@/assets/images/media/pinglun.png')"
)
p.funtext 评论
li.funLi
van-image.funImg(
width="0.54rem",
height="0.54rem",
fit="cover",
:src="require('@/assets/images/media/shoucang.png')"
)
p.funtext 收藏
li.funLi
van-image.funImg(
width="0.54rem",
height="0.54rem",
fit="cover",
:src="require('@/assets/images/media/dianzan.png')"
)
p.funtext 点赞
van-action-sheet.audioSheet(v-model:show="sheetShow", :title="sheetTit")
.sheetCon
.multipW(v-if="sheetConActive == 'beisu'")
.multipInfo(
v-for="(item, index) in multipleArray",
:key="index",
@click="multipSelect(item.num, index)"
)
.multipText(:class="item.isSelected ? 'isSelect' : ''") {{ item.text }}
van-icon.multipIcon(
:name="require('@/assets/images/media/isSelected.png')",
size="0.7rem",
v-if="item.isSelected"
)
.catalogW(v-if="sheetConActive == 'mulu'")
.catalogInfo(
v-for="(item, index) in catalogArray",
:key="index",
@click="catalogSelect(index)"
)
.catalogCon(:class="item.isPlay ? 'isPlay' : ''")
.con_box
.con_boxTit {{ index + 1 }}.{{ item.title }}
.con_boxDesc {{ item.desc }}
.con_boxIcon
van-icon.timeIcon(name="clock-o", size="0.2rem")
span.timeSpan {{ item.audioDurat }}
van-image.con_Img(
width="0.6rem",
height="0.6rem",
fit="cover",
:src="item.isPlay ? require('@/assets/images/media/playing.gif') : require('@/assets/images/media/playMl.png')"
)
.reviewW(v-if="sheetConActive == 'pinglun'")
.reviewInfo 评论内容
</template>

二、ts部分

<script lang="ts">
import {
defineComponent,
onBeforeMount,
reactive,
ref,
toRefs,
} from "vue"; interface control {
audioUrl: string;
play: boolean;
} export default defineComponent({
name: "audioPlay",
setup() {
const audioControl: control = reactive({ audioUrl: "", play: false });
onBeforeMount(() => {
audioInfo.audioSrc = (catalogArray as any).value[0].audioSrc;
audioInfo.title = (catalogArray as any).value[0].title;
audioInfo.duration = (catalogArray as any).value[0].audioDurat;
setTimeout(() => {
audioInfo.isSlide = audio.value.duration;
console.log("audio.value.duration22", typeof audio.value.duration);
// alert(audio.value.duration);
}, 100);
}); //暂停播放
const handlePlayer = (): void => {
audioControl.play = !audioControl.play;
audioControl.play
? (audio.value as any).play()
: (audio.value as any).pause();
}; const audioInfo = reactive({
audioSrc: "",
backSecond: 15, //后退秒数
forwardSecond: 15, //前进秒数
duration: "00:00", //音频总时长
currentDuration: "00:00", //音频当前播放时长
title: "",
paused: true,
isPlayNum: 1, //上下集用到-正在播放的第几集
isSlide: 0, //判断滑块是否可以滑动
});
const audio = ref();
const sliderValue = ref();
//后退
const handleBack = (): void => {
if (audio.value.currentTime > audioInfo.backSecond) {
audio.value.currentTime =
audio.value.currentTime - audioInfo.backSecond;
}
};
//前进
const handleForward = (): void => {
if (
audio.value.duration - audio.value.currentTime >
audioInfo.forwardSecond
) {
audio.value.currentTime =
audio.value.currentTime + audioInfo.forwardSecond;
}
};
//暂停或播放
const handlePauseOrPlay = (): void => {
console.log("audio.value.duration22", typeof audio.value.duration);
setTimeout(() => {
audio.value.paused ? audio.value.play() : audio.value.pause();
audioInfo.paused = !audioInfo.paused;
}, 200);
};
//视频在可以播放时触发
const getDuration = (): void => {
setTimeout(() => {
(audioInfo.duration as any) = timeFormat(audio.value.duration);
}, 200);
};
//将单位为秒的的时间转换成mm:ss的形式
const timeFormat = (number: Number) => {
let minute = parseInt((<number>number / 60) as any);
let second = parseInt((<number>number % 60) as any);
(minute as any) = minute >= 10 ? minute : "0" + minute;
(second as any) = second >= 10 ? second : "0" + second;
return minute + ":" + second;
};
//进度条发生变化时触发
const updateTime = (): void => {
audioInfo.currentDuration = timeFormat(audio.value.currentTime);
sliderValue.value = (
(audio.value.currentTime * 100) /
audio.value.duration
).toFixed(3);
audioInfo.isSlide = audio.value.duration;
// 播放完毕按钮变回
if (audioInfo.currentDuration == audioInfo.duration) {
audioInfo.paused = true;
}
};
//滑动进度条
const sliderOnChange = (value: any): void => {
console.log("value", timeFormat((audio.value.duration * value) / 100));
// 设置播放时间
audioInfo.currentDuration = timeFormat(
(audio.value.duration * value) / 100
);
audio.value.currentTime = parseInt(
((audio.value.duration * value) / 100) as any
);
};
// 点击右侧功能
const sheetShow = ref(false);
const sheetTit = ref("");
const sheetConActive = ref("");
const multipleArray = ref([
{ num: 0.75, text: "0.75X", isSelected: false },
{ num: 1, text: "1.0X(正常倍速)", isSelected: true },
{ num: 1.25, text: "1.25X", isSelected: false },
{ num: 1.5, text: "1.5X", isSelected: false },
{ num: 2, text: "2X", isSelected: false },
]);
const catalogArray = ref([
{
title: "音频播放器第一曲",
desc: "第一站《大宪章》纪念碑1/4",
audioSrc: require("@/assets/images/media/audio/music1.mp3"),
audioDurat: "04:07",
isPlay: true,
},
{
title: "测试二未过时的未过时仍未未过时的未过时过时的未过时的未过",
desc: "第一站测试二未过时的未过时仍未未过时的未过时过时的未过时的",
audioSrc: require("@/assets/images/media/audio/music2.mp3"),
audioDurat: "02:06",
isPlay: false,
},
{
title: "测试三过时未过时的未过时",
desc: "第一站测试三未过时的未过时仍未未过时的未过时过时的未过时的/4",
audioSrc: require("@/assets/images/media/audio/music3.mp3"),
audioDurat: "04:56",
isPlay: false,
},
]); // 下方功能唤起面板
const sheetShowCli = (val: any, tit: any): void => {
sheetConActive.value = val;
sheetTit.value = tit;
sheetShow.value = true;
};
// 倍速选择
const multipSelect = (num: Number, index: number): void => {
audio.value.playbackRate = num;
multipleArray.value.forEach((item: any) => {
item.isSelected = false;
});
multipleArray.value[index].isSelected = true;
sheetShow.value = false;
};
// 选集功能
const catalogSelect = (index: number): void => {
catalogArray.value.forEach((item: any) => {
item.isPlay = false;
});
sliderValue.value = 0;
audio.value.currentTime = 0;
audioInfo.paused = true;
audioInfo.audioSrc = (catalogArray as any).value[index].audioSrc;
audioInfo.title = (catalogArray as any).value[index].title;
audioInfo.currentDuration = "00:00";
audioInfo.duration = (catalogArray as any).value[index].audioDurat;
catalogArray.value[index].isPlay = true;
sheetShow.value = false;
audioInfo.isPlayNum = index + 1;
handlePauseOrPlay();
};
// 上一集
const prevPlay = (num: any): void => {
if (num > 1) {
catalogArray.value.forEach((item: any) => {
item.isPlay = false;
});
sliderValue.value = 0;
audio.value.currentTime = 0;
audioInfo.paused = true;
audioInfo.audioSrc = (catalogArray as any).value[num - 2].audioSrc;
audioInfo.title = (catalogArray as any).value[num - 2].title;
audioInfo.currentDuration = "00:00";
audioInfo.duration = (catalogArray as any).value[num - 2].audioDurat;
catalogArray.value[num - 2].isPlay = true;
audioInfo.isPlayNum = num - 1;
sheetShow.value = false;
handlePauseOrPlay();
}
};
// 下一集
const nextPlay = (num: any): void => {
if (num < catalogArray.value.length) {
catalogArray.value.forEach((item: any) => {
item.isPlay = false;
});
sliderValue.value = 0;
audio.value.currentTime = 0;
audioInfo.paused = true;
audioInfo.audioSrc = (catalogArray as any).value[num].audioSrc;
audioInfo.title = (catalogArray as any).value[num].title;
audioInfo.currentDuration = "00:00";
audioInfo.duration = (catalogArray as any).value[num].audioDurat;
catalogArray.value[num].isPlay = true;
audioInfo.isPlayNum = num + 1;
sheetShow.value = false;
handlePauseOrPlay();
}
};
return {
...toRefs(audioControl),
handlePlayer, ...toRefs(audioInfo),
handleBack,
handleForward,
handlePauseOrPlay,
getDuration,
updateTime,
audio,
sliderValue,
sliderOnChange,
sheetShow,
multipleArray,
sheetShowCli,
sheetTit,
sheetConActive,
multipSelect,
catalogArray,
catalogSelect,
prevPlay,
nextPlay,
};
},
});
</script>

三、样式部分

<style lang="scss">
.audioSlider {
.van-slider__bar {
z-index: 1111;
}
&.van-slider--disabled {
opacity: 1;
}
}
.isPlay {
.con_Img {
.van-image__img {
width: 0.4rem;
height: 0.4rem;
}
}
}
</style>
<style lang="scss" scoped>
.audioPlay {
height: 100vh;
display: flex;
flex-direction: column;
.content {
@include Padding(0.2rem, 0px);
@include Position(relative, 0, -0.9rem);
width: 100%;
}
main {
flex: 1;
overflow: auto;
.audioBox {
.imgBox {
width: 100%;
text-align: center;
margin-top: 1.1rem;
}
}
.titBox {
width: 1.8rem;
height: 0.6rem;
border-radius: 0.3rem;
border: 1px solid #d8be98;
text-align: center;
margin: 0.6rem auto 0;
font-size: 0.32rem;
line-height: 0.6rem;
color: #d8be98;
box-sizing: border-box;
}
.titText {
width: 80%;
margin: 0.3rem auto 0;
@include textEllipsis();
font-size: 0.36rem;
line-height: 0.4rem;
color: #333;
text-align: center;
}
.audioControl {
position: relative;
&::before {
position: absolute;
top: 0;
left: 0;
width: 50%;
content: "";
height: 2px;
background: #d8be98;
}
&::after {
position: absolute;
top: 0;
right: 0;
width: 50%;
content: "";
height: 2px;
background: #e0e0e0;
}
width: 90%;
position: absolute;
bottom: 0.6rem;
left: 50%;
transform: translateX(-50%);
.audioSlider {
width: 80%;
margin: 0 auto; .custom-button {
background: #d8be98;
padding: 0 0.14rem;
height: 0.36rem;
line-height: 0.4rem;
border-radius: 0.18rem;
font-size: 0.24rem;
color: #000;
transform: scale(0.9);
}
}
.handleUl {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 0.1rem;
box-sizing: border-box;
margin-top: 0.4rem;
.handleLi {
line-height: 0;
}
}
}
.funUl {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 0.7rem;
.funLi {
line-height: 0; .funtext {
color: #999999;
font-size: 0.24rem;
line-height: 0.4rem;
}
}
}
}
.audioSheet {
.sheetCon {
border-top: 1px solid #dfdfdf;
.multipW {
padding: 0 0.32rem 1rem;
.multipInfo {
border-bottom: 1px solid #dfdfdf;
height: 0.86rem;
display: flex;
justify-content: space-between;
align-items: center;
.multipText {
color: #666666;
font-size: 0.32rem;
&.isSelect {
color: #caaa7c;
}
.multipIcon {
color: #caaa7c;
}
}
}
}
.catalogW {
padding: 0 0.32rem 0.6rem;
.catalogInfo {
border-bottom: 1px solid #e6e6e6;
.catalogCon {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.24rem 0.2rem 0.24rem 0;
box-sizing: border-box;
.con_box {
width: 80%;
.con_boxTit {
width: 100%;
@include textEllipsis();
font-size: 0.32rem;
color: #000000;
}
.con_boxDesc {
font-size: 0.28rem;
color: #999999;
@include textEllipsis();
margin-top: 0.1rem;
}
.con_boxIcon {
color: #cccccc;
font-size: 0.24rem;
margin-top: 0.2rem;
.timeIcon {
margin-right: 0.1rem;
}
}
}
&.isPlay {
.con_box {
.con_boxTit {
color: #caaa7c;
}
.con_boxDesc {
color: #e0ccb1;
}
.con_boxIcon {
color: #e0ccb1;
}
}
}
.con_Img {
background: #f7f1e8;
width: 0.6rem;
height: 0.6rem;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
}
.reviewW {
padding: 0 0.32rem 0.6rem;
.reviewInfo {
border-bottom: 1px solid #e6e6e6;
padding: 0.4rem 0;
.reviewCon {
display: flex;
justify-content: space-between;
.con_box {
width: calc(100% - 0.78rem);
.con_boxTit {
font-size: 0.28rem;
color: #666666;
}
.con_boxTime {
color: #b3b3b3;
font-size: 0.24rem;
line-height: 0.4rem;
}
.con_boxText {
font-size: 0.32rem;
color: #333333;
line-height: 0.48rem;
}
.con_boxReply {
background: #f8f8f8;
width: 100%;
padding: 0.1rem 0.2rem 0.2rem;
box-sizing: border-box;
margin-top: 0.2rem;
.replyList {
display: flex;
font-size: 0.28rem;
line-height: 0.36rem;
margin-top: 0.1rem;
.replyName {
color: #666;
white-space: nowrap;
margin-right: 0.1rem;
}
.replyText {
color: #333;
}
}
}
}
}
}
}
}
}
@media only screen and (min-width: 750px) {
.audioPlay {
@include boxSize(750px, 100vh);
margin: 0 auto;
}
}
</style>

做个笔记

vue3+ts+vant制作音乐播放器(进度条拖拽、倍速切换、上一曲、下一曲)完整版的更多相关文章

  1. HTML+纯JS制作音乐播放器

    该篇文章会教你通过JavaScript制作一个简单的音乐播放器.包括播放.暂停.上一曲和下一曲. 阅读本文章你需要对HTML.CSS和Javascript有基本的了解. 话不多说,先上图. emmm. ...

  2. Android 音视频深入 十三 OpenSL ES 制作音乐播放器,能暂停和调整音量(附源码下载)

    项目地址https://github.com/979451341/OpenSLAudio OpenSL ES 是基于NDK也就是c语言的底层开发音频的公开API,通过使用它能够做到标准化, 高性能,低 ...

  3. Qt+MPlayer音乐播放器开发笔记(一):ubuntu上编译MPlayer以及Demo演示

    前言   在ubuntu上实现MPlayer播放器播放音乐.   Demo                Mplayer   MPlayer是一款开源多媒体播放器,以GNU通用公共许可证发布.此款软件 ...

  4. html5+css3 制作音乐播放器

    //css// body , html{    margin:0;    padding:0;    font:12px Arial, Helvetica, sans-serif;    } .Mus ...

  5. 开源播放器 ijkplayer (二) :ijkplayer倍速变调问题解决方案

    转载注明出处:http://www.cnblogs.com/renhui/p/6510872.html 之前使用IjkPlayer做播放器的使用的时候,在做倍速播放的时候,发现播放的声音音调明显变高了 ...

  6. JavaScript实现水平进度条拖拽效果

    <html> <head> <meta charset="UTF-8"> <title>Document</title> ...

  7. 使用 原生js 制作插件 (javaScript音乐播放器)

    1.引用页面 index.html <!DOCTYPE html> <html lang="en"> <head> <meta chars ...

  8. 【重点突破】——Canvas技术绘制音乐播放器界面

    一.引言 在用Canvas练习制作了验证码之后,还有一个用Canvas技术很综合的练习——制作音乐播放器.在做这个练习的过程中,还有一个重要的观察点,那就是理解Canvas的一大问题. 二.要求  点 ...

  9. ios开发:一个音乐播放器的设计与实现

    github地址:https://github.com/wzpziyi1/MusicPlauer 这个Demo,关于歌曲播放的主要功能都实现了的.下一曲.上一曲,暂停,根据歌曲的播放进度动态滚动歌词, ...

  10. vue实现音乐播放器实战笔记

    原文链接:https://blog.csdn.net/Forever201295/article/details/80266600 一.项目说明该播放器的是基于学习vue的实战练习,不用于其他途径.应 ...

随机推荐

  1. linux服务器连接数查询

    linux服务器环境检查 CPU.内存使用情况 查看系统整体执行情况 命令执行 # 查看当前系统正在执行的进程的相关信息,包括进程ID.内存占用率.CPU占用率等 top # 返回结果 # 14:06 ...

  2. Ubuntu子系统shell脚本自动连接xfce4界面

    脚本功能 命令行参数指定ip连接/获取ifconfig中的本地ip连接 修改.bashrc #!/bin/bash net_dev="wifi0" #默认的设备名 FALSE=&q ...

  3. 利用拉格朗日乘子法从最优化问题中推导出KKT条件

    优化问题的一般形式 在优化问题中,我们将其一般形式定义为有约束(不等式约束.等式约束)的最小化优化问题,其具体定义如下: \[\begin{array}{ll} \min _{x} & f_{ ...

  4. Kubernetes--管理Pod对象的容器(3)

    共享节点的网络名称空间 同一个Pod对象的各容器均运行于一个独立的.隔离的Network名称空间中,共享同一个网络协议栈及相关的网络设备.也有一些特殊的Pod对象需要运行于所在节点的名称空间中,执行系 ...

  5. Selenium私房菜系列7 -- 深入了解Selenium RC工作原理(2)【II】

    继续前一篇的问题,为什么Selenium RC中的Selenium Server需要以这种代理服务器的形式存在?其实,这和浏览器的"同源策略"(The Same Origin Po ...

  6. Pytorch加载txt格式的数据集文件(以PTB数据集为例)

    前言 这篇博客以PTB数据集为例,详细讲解了如何将txt格式的数据集文件,转换为pytorch框架可以直接处理的tensor变量,并附上相应代码 @ 目录 前言 1. PTB 数据集 2. 构建词汇表 ...

  7. 路飞前台全局css 全局配置文件,安装axios,安装vue-cookies,安装elementui,安装bootstrap和jq,后台主页模块表设计,后台主页模块轮播图接口,录入数据,跨域问题详解

    目录 路飞前台全局css 全局配置文件,安装axios,安装vue-cookies,安装elementui,安装bootstrap和jq,后台主页模块表设计,后台主页模块轮播图接口,录入数据,跨域问题 ...

  8. 集群activemq重启报错java.lang.OutOfMemoryError: GC overhead limit exceeded

    最近安全部门同事说我们环境有个弱密码漏洞,activemq后台的密码不够复杂,需要改为复杂密码. 我登录了他们扫出来的url,输入admin admin,果然进来了.不得不说上一位已离职同事的安全意识 ...

  9. (1019) rapidsvn 安装

    https://blog.csdn.net/mzpmzk/article/details/106332039

  10. 内存模型--共享、JMM

    Balking 指令重排