vue2.0 结合HTML5原生Audio标签在移动端的使用实现方式,应用场景为钉钉微应用
在做vue2.0钉钉微应用项目,有需要播放音频的是需求,用阿里云sdk播放器不购买相关服务,音频有些播放不了。于是我就直接用HTML5原生的Audio标签自己写音频播放器。(业务需求:记录上次播放位置并从上次播放位置播放,观看进度不满100%不允许快进,满100%方可快进。)以下是整个业务代码:CSS部分:.audio-box{height:100%;width:100%...
·
在做vue2.0钉钉微应用项目,有需要播放音频的是需求,用阿里云sdk播放器不购买相关服务,音频有些播放不了。于是我就直接用HTML5原生的Audio标签自己写音频播放器。(业务需求:记录上次播放位置并从上次播放位置播放,观看进度不满100%不允许快进,满100%方可快进。)以下是整个业务代码:
CSS部分:
.audio-box{
height:100%;
width:100%;
background:rgba(16,32,56,.9);
position:relative;
z-index:3000;
.audio-name{
width:100%;
font-size:.14rem;
color:#eee;
position:absolute;
left:0;
top: .30rem;
text-align:center;
@include ellipsis();
}
.perisphere{
width:3rem;
height:3rem;
background:rgba(255,255,255,.3);
border-radius:100%;
-moz-border-radius: 100%;
-webkit-border-radius: 100%;
position:absolute;
left:0;
bottom:0;
top:0;
right:0;
margin:auto;
z-index:3005;
@include flexbox();
@include flex-direction(row);
@include justify-content(center);
@include align-items(center);
.audio-show-img-box{
width:2.5rem;
height:2.5rem;
border-radius:100%;
-moz-border-radius: 100%;
-webkit-border-radius: 100%;
@include flexbox();
@include flex-direction(row);
@include justify-content(center);
@include align-items(center);
#audio-show-img{
width:100%;
height:100%;
border-radius:100%;
-moz-border-radius: 100%;
-webkit-border-radius: 100%;
}
.audio-play-show {
-webkit-animation: say 12s linear infinite;
-moz-animation: say 12s linear infinite;
-ms-animation: say 12s linear infinite;
-o-animation: say 12s linear infinite;
animation: say 12s linear infinite;
}
.audio-pause-show {
-webkit-animation: stopSay 2s linear infinite;
-moz-animation: stopSay 2s linear infinite;
-ms-animation: stopSay 2s linear infinite;
-o-animation: stopSay 2s linear infinite;
animation: stopSay 2s linear infinite;
}
@-webkit-keyframes say {
0% {}
100% {
-webkit-transform: rotateZ(360deg);
}
}
@-moz-keyframes say {
0% {}
100% {
-moz-transform: rotateZ(360deg);
}
}
@-ms-keyframes say {
0% {}
100% {
-ms-transform: rotateZ(360deg);
}
}
@-o-transforms say {
0% {}
100% {
-o-transform: rotateZ(360deg);
}
}
@keyframes say {
0% {}
100% {
transform: rotateZ(360deg);
}
}
@-webkit-keyframes stopSay {
0% {}
100% {
-webkit-transform: rotateZ(0);
}
}
@-moz-keyframes stopSay {
0% {}
100% {
-moz-transform: rotateZ(0);
}
}
@-ms-keyframes stopSay {
0% {}
100% {
-ms-transform: rotateZ(0);
}
}
@-o-transforms stopSay {
0% {}
100% {
-o-transform: rotateZ(0);
}
}
@keyframes stopSay {
0% {}
100% {
transform: rotateZ(0);
}
}
}
.audio-play-img-box{
width:2.5rem;
height:2.5rem;
border-radius:100%;
-moz-border-radius: 100%;
-webkit-border-radius: 100%;
position:absolute;
left:0;
bottom:0;
top:0;
right:0;
margin:auto;
z-index:4100;
@include flexbox();
@include flex-direction(row);
@include justify-content(center);
@include align-items(center);
display:none;
.show-play-img{
height:1rem;
width:1rem;
margin:.75rem 0 0 .75rem;
cursor:pointer;
}
}
}
.load-title{
width:100%;
font-size:.12rem;
color:#eee;
position:absolute;
left:0;
bottom: .54rem;
text-align:center;
@include ellipsis();
}
.audio-control{
width:100%;
height:.44rem;
background:rgba(0,0,0,.6);
position:absolute;
left:0;
bottom:0;
z-index:3100;
@include flexbox();
@include flex-direction(row);
@include justify-content(space-around);
@include align-items(center);
.audio-play-control{
height:.26rem;
width:.22rem;
background:url('../../static/icon-audio-pause.png') no-repeat center center;
background-size:100% 100%;
margin-left:.12rem;
cursor:pointer;
}
.size{
font-size:.12rem;
color:#fff;
float: left;
display: block;
}
.timeshow{
font-size:.12rem;
color:#fff;
float: right;
display: block;
}
.right-timeUpdata{
height:100%;
width:2rem;
@include flexbox();
@include flex-direction(row);
@include align-items(center);
.timeline{
height: .04rem;
width:100%;
background-color: rgba(256, 256, 256, 0.6);
border-radius: 5px;
position: relative;
z-index: 3100;
span{
position: relative;
width: 0px;
height: .04rem;
background: #0188fd;
box-shadow: inset 1px 1px 1px 0 rgba(0,0,0,.06);
border-radius: .10rem;
-moz-border-radius: .10rem;
-webkit-border-radius: .10rem;
display: block;
-webkit-transition: width ease-out 0.3s;
-o-transition: width ease-out 0.3s;
transition: width ease-out 0.3s;
}
span:after{
content: "";
position: absolute;
top: -.05rem;
right: 0;
width: .12rem;
height: .12rem;
border-radius: 100%;
-moz-border-radius: 100%;
-webkit-border-radius: 100%;
background: #0188fd;
}
}
}
}
}
HTMl部分:
<template>
<div class="audio-box">
<audio id="audio" preload="auto"></audio>
<p class="audio-name"></p>
<div class="perisphere">
<div class="audio-show-img-box">
<img class="images" id="audio-show-img" src="../../../static/icon-audio-show.png" />
</div>
<div class="audio-play-img-box" id="audio-play-img-box">
<img id="show-play-img" class="show-play-img images" src="../../../static/icon-audio-bag-play.png" />
</div>
</div>
<p class="load-title" id="load-title">正在缓冲…</p>
<div class="audio-control">
<div class="audio-play-control" id="audio-play-control"></div>
<span class="size" id="size">00:00</span>
<div class="right-timeUpdata">
<p class="timeline" id="timeline"><span id="progress"></span></p>
</div>
<span class="timeshow" id="timeshow">00:00</span>
</div>
</div>
</template>
js部分:
<script type="text/javascript">
import axios from 'axios';
import router from '../../router';
import { Toast } from 'mint-ui';
import { global_set } from '../../script/global.js';
export default {
data() {
return {
planId: this.$route.query.planId, //学习计划id
courseId: this.$route.query.courseId, //课程id
token: this.$route.query.access_token,
resourceId: this.$route.query.resourceId,
playContent: '',
}
},
created() {
},
mounted() {
axios.get(global_set.host + "/plan/myTask/getSingleResourceProgress", {
params: {
access_token: this.token,
courseId: this.courseId,
planId: this.planId,
resourceId: this.resourceId, //加资源id
timeStamp: Date.parse(new Date()),
}
})
.then((data) => {
this.playContent = data.data.data;
var that = this;
//音频标题设置
$('.audio-name').html(that.playContent.name)
/*********************mp3************************/
that.$nextTick(function() {
var onoff = false,
audio = document.getElementById('audio'),
isPalyControl = document.getElementById('audio-play-control'),
showPalyImgBox = document.getElementById('audio-play-img-box'),
showPalyImg = document.getElementById('show-play-img'),
audioShowImg = document.getElementById('audio-show-img'),
timeline = document.getElementById('timeline'),
progress=document.getElementById('progress'), //进度条
timeshow=document.getElementById('timeshow'), //总时间
size=document.getElementById('size'), //时时显示时间
loadTitle=document.getElementById('load-title'); //缓冲显示
//是否允许快进
var progressBtn = that.playContent.studyProgress;
//上次播放位置记录
var recentStart = that.playContent.recentStart;
audio.src = that.playContent.url;
audioPlay();
var button=true;
audio.addEventListener("canplay",function() {
//设置初始播放位置
var seekable = this.seekable && this.seekable.length > 0;
if(seekable && button){
var that=this;
setTimeout(function(){
that.currentTime = recentStart;
button=false;
},500)
}
});
//绑定timeupdate事件
audio.addEventListener('timeupdate', function() {
//获取当前的播放时刻(单位秒)
var currentTimes = audio.currentTime;
if(!isNaN(audio.duration)) {
//播放时间显示
setTimeShow();
//用时间比来获取进度条的值
var progressValue = audio.currentTime / audio.duration;
if(progressValue == 1) {
//当前播放完成停止播放
audioPause();
onoff = true;
//播放完进度保存
var durations = audio.duration; //获取获取视频总时长(单位秒)
var percents = Math.round(currentTimes * 100 / durations); //四舍五入进度
var tempTimeEnd = parseInt(currentTimes, 10); //当前播放时刻转换
//intervalFun(percents, tempTimeEnd);
}
};
}, false);
audio.addEventListener("pause",
function() { //音频监听暂停时保存当前进度
var currentTime = audio.currentTime; //获取当前的播放时刻(单位秒)
var duration = audio.duration; //获取获取视频总时长(单位秒)
var percent = Math.round(currentTime * 100 / duration); //四舍五入进度
var tempTimes = parseInt(currentTime, 10); //当前播放时刻转换
intervalFun(percent, tempTimes); //调取延时请求函数saveTask
}, false);
// 进度条控制
timeline.addEventListener('touchend', function(e) {
var x = e.changedTouches[0].clientX - this.offsetLeft;
var X = x < 0 ? 0 : x;
var W =this.offsetWidth;
var place = X > W ? W : X;
//是否允许用户快进
if(progressBtn >= 100) {
audio.currentTime = (place / W).toFixed(2) * audio.duration
progress.style.width=(place / W).toFixed(2) * 100 + "%";
}
});
// 设置播放时间
function setTimeShow() {
var playTime = secondToMin(audio.currentTime);
var duration = audio.duration === Infinity ? null : audio.duration;
var durations=secondToMin(duration);
loadTitle.style.display='none';
size.innerHTML=playTime;
timeshow.innerHTML=durations;
progress.style.width=( audio.currentTime / duration).toFixed(4) * 100 + "%"
}
// 计算时间
function secondToMin(s) {
var MM = Math.floor(s / 60);
var SS = s % 60;
if(MM < 10) {
MM = "0" + MM;
}
if(SS < 10) {
SS = "0" + SS;
}
var min = MM + ":" + SS;
return min.split('.')[0];
}
isPalyControl.onclick = function() {
palyControl();
onoff = !onoff;
}
showPalyImg.onclick = function() {
palyControl();
onoff = !onoff;
}
//播放暂停切换
function palyControl() {
if(onoff) {
audioPlay();
} else {
audioPause();
}
}
//播放
function audioPlay() {
audio.play();
//console.log(audio.networkState) //0.此元素未初始化 1.正常但没有使用网络 2.正在下载数据 3.没有找到资源
if(audio.error != null) {
console.log(audio.error.code) //1.用户终止 2.网络错误 3.解码错误 4.URL无效
}
isPalyControl.style.height = 0.26 + 'rem';
isPalyControl.style.background = 'url("../../../static/icon-audio-pause.png") no-repeat center center';
isPalyControl.style.backgroundSize = '100% 100%';
showPalyImgBox.style.display = 'none';
//播放动效
audioShowImg.style.animation = 'say 12s linear infinite';
audioShowImg.style.WebkitAnimation = 'say 12s linear infinite';
audioShowImg.style.MozAnimation = 'say 12s linear infinite';
audioShowImg.style.MsAnimation = 'say 12s linear infinite';
audioShowImg.style.OAnimation = 'say 12s linear infinite';
// $('#audio-show-img').css({"-webkit-animation":"say 12s linear infinite","-moz-animation":"say 12s linear infinite","-ms-animation":"say 12s linear infinite","animation":"say 12s linear infinite"});
};
//暂停
function audioPause() {
audio.pause();
isPalyControl.style.height = 0.22 + 'rem';
isPalyControl.style.background = 'url("../../../static/icon-audio-play.png") no-repeat center center';
isPalyControl.style.backgroundSize = '100% 100%';
showPalyImgBox.style.display = 'block';
//关闭播放动效
audioShowImg.style.animation = 'stopSay 2s linear infinite';
audioShowImg.style.WebkitAnimation = 'stopSay 2s linear infinite';
audioShowImg.style.MozAnimation = 'stopSay 2s linear infinite';
audioShowImg.style.MsAnimation = 'stopSay 2s linear infinite';
audioShowImg.style.OAnimation = 'stopSay 2s linear infinite';
// $('#audio-show-img').css({"-webkit-animation":"stopSay 2s linear infinite","-moz-animation":"stopSay 2s linear infinite","-ms-animation":"stopSay 2s linear infinite","animation":"stopSay 2s linear"});
};
//保存audio进度
function intervalFun(progre, times) {
axios.post(global_set.host + "/plan/myTask/saveTask", $.param({
access_token: that.token,
planId: that.planId,
courseId: that.courseId,
resourceId: that.resourceId,
courseType: 2,
progress: progre,
tempTime: times,
timeStamp: Date.parse(new Date()),
}))
.then((data) => {
})
.catch(function(err) {
})
};
})
})
.catch(function(err) {
//console.log(err);
})
},
}
</script>
效果如下:
更多推荐
已为社区贡献7条内容
所有评论(0)