You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
279 lines
6.7 KiB
279 lines
6.7 KiB
7 months ago
|
<template>
|
||
|
<view class="audio-warp" @click="handleBtnClick">
|
||
|
<view class="cover-warp" :class="{ hasbg: !poster }">
|
||
|
<image :src="poster" v-if="poster" class="cover-img"></image>
|
||
|
<view class="play-btn" :class="{ pause: play }"></view>
|
||
|
</view>
|
||
|
<view class="audio-con">
|
||
|
<view class="info">
|
||
|
<text class="audio-title am-text-eill">{{ name }}</text>
|
||
|
<!-- <text class="audio-author am-text-eill">{{ author }}</text> -->
|
||
|
<text class="audio-author am-text-eill">{{ audioTimeUpdate }}</text>
|
||
|
<slider class="audio-slider" activeColor="#fae68f" block-size="12" block-color="#c0947d" :value="current" :max="duration" @changing="changing" @change="change"></slider>
|
||
|
</view>
|
||
|
<!-- <view class="audio-time">{{ audioTimeUpdate }}</view> -->
|
||
|
</view>
|
||
|
</view>
|
||
|
</template>
|
||
|
|
||
|
<script>
|
||
|
/**
|
||
|
* luch-audio 0.0.1
|
||
|
* @module luch-audio
|
||
|
* @Author lu-ch
|
||
|
* @Date 2019-06-11
|
||
|
* @Email webwork.s@qq.com
|
||
|
* @description 音频播放组件,使用了createInnerAudioContext
|
||
|
*/
|
||
|
/**
|
||
|
* Props itemsProps
|
||
|
* @prop {Boolean} play - 是否播放,双向绑定,绑定时需使用.sync 如果为true 则播放,为false 则暂停
|
||
|
* ... 其他api同文档 (https://uniapp.dcloud.io/api/media/audio-context?id=createinneraudiocontext)
|
||
|
*/
|
||
|
/**
|
||
|
* 将秒转换为 分:秒
|
||
|
* @param {Number} s - 秒数
|
||
|
*/
|
||
|
function sToHs(s) {
|
||
|
//计算分钟
|
||
|
//算法:将秒数除以60,然后下舍入,既得到分钟数
|
||
|
let h;
|
||
|
h = Math.floor(s / 60);
|
||
|
//计算秒
|
||
|
//算法:取得秒%60的余数,既得到秒数
|
||
|
s = s % 60;
|
||
|
//将变量转换为字符串
|
||
|
h += '';
|
||
|
s += '';
|
||
|
//如果只有一位数,前面增加一个0
|
||
|
h = (h.length === 1) ? '0' + h : h;
|
||
|
s = (s.length === 1) ? '0' + s : s;
|
||
|
return h + ':' + s;
|
||
|
}
|
||
|
export default {
|
||
|
name: 'ComAudio',
|
||
|
props: {
|
||
|
play: {
|
||
|
type: Boolean,
|
||
|
required: true
|
||
|
},
|
||
|
src: {
|
||
|
type: String
|
||
|
},
|
||
|
poster: {
|
||
|
type: String,
|
||
|
default: ''
|
||
|
},
|
||
|
name: {
|
||
|
type: String,
|
||
|
default: '未知音频'
|
||
|
},
|
||
|
author: {
|
||
|
type: String,
|
||
|
default: '本站编辑'
|
||
|
},
|
||
|
autoplay: {
|
||
|
type: Boolean,
|
||
|
default: false
|
||
|
},
|
||
|
loop: {
|
||
|
type: Boolean,
|
||
|
default: false
|
||
|
},
|
||
|
obeyMuteSwitch: {
|
||
|
type: Boolean,
|
||
|
default: true
|
||
|
}
|
||
|
},
|
||
|
data() {
|
||
|
return {
|
||
|
audioTimeUpdate: '00:00',
|
||
|
innerAudioContext: '',
|
||
|
currentTime: '', //当前播放时间
|
||
|
durationTime: '', //总时长
|
||
|
duration: '',
|
||
|
current: '', //slider当前进度
|
||
|
loading: false, //是否处于读取状态
|
||
|
paused: true, //是否处于暂停状态
|
||
|
seek: false //是否处于拖动状态
|
||
|
};
|
||
|
},
|
||
|
methods: {
|
||
|
//格式化时长
|
||
|
format(num) {
|
||
|
return '0'.repeat(2 - String(Math.floor(num / 60)).length) + Math.floor(num / 60) + ':' + '0'.repeat(2 - String(
|
||
|
Math.floor(num % 60)).length) + Math.floor(num % 60)
|
||
|
},
|
||
|
changing(e) {
|
||
|
this.seek = false;
|
||
|
this.current = e.detail.value;
|
||
|
//this.innerAudioContext.pause();
|
||
|
this.$emit('update:play', false);
|
||
|
},
|
||
|
//完成拖动事件
|
||
|
change(e) {
|
||
|
this.current = e.detail.value;
|
||
|
this.innerAudioContext.seek(this.current);
|
||
|
console.log(this.current);
|
||
|
//this.innerAudioContext.play();
|
||
|
this.$emit('update:play', true);
|
||
|
// this.audioTimeUpdate = sToHs(Math.floor(this.innerAudioContext.duration-this.innerAudioContext.currentTime));
|
||
|
this.audioTimeUpdate = sToHs(Math.floor(this.innerAudioContext.currentTime));
|
||
|
},
|
||
|
audioPlay() {
|
||
|
this.$emit('update:play', true);
|
||
|
},
|
||
|
audioPause() {
|
||
|
this.$emit('update:play', false);
|
||
|
},
|
||
|
handleBtnClick() {
|
||
|
// this.$emit('update:play', !this.play);
|
||
|
this.$emit('change', !this.play);
|
||
|
},
|
||
|
contextInit() {
|
||
|
// console.log('创建');
|
||
|
let that = this;
|
||
|
that.$emit('update:play', false);
|
||
|
let innerAudioContext = uni.createInnerAudioContext();
|
||
|
innerAudioContext.autoplay = that.autoplay;
|
||
|
innerAudioContext.src = that.src;
|
||
|
innerAudioContext.loop = that.loop;
|
||
|
innerAudioContext.obeyMuteSwitch = that.obeyMuteSwitch;
|
||
|
that.current = 0
|
||
|
innerAudioContext.onPlay(function() {
|
||
|
// that.audioTimeUpdate = sToHs(Math.floor(innerAudioContext.duration-innerAudioContext.currentTime));
|
||
|
that.audioTimeUpdate = sToHs(Math.floor(innerAudioContext.currentTime));
|
||
|
that.durationTime = sToHs(Math.floor(innerAudioContext.duration));
|
||
|
that.audioPlay();
|
||
|
});
|
||
|
innerAudioContext.onPause(function() {
|
||
|
that.audioPause();
|
||
|
});
|
||
|
innerAudioContext.onEnded(function() {
|
||
|
that.audioPause();
|
||
|
});
|
||
|
innerAudioContext.onTimeUpdate(function() {
|
||
|
// that.audioTimeUpdate = sToHs(Math.floor(innerAudioContext.duration-innerAudioContext.currentTime));
|
||
|
that.audioTimeUpdate = sToHs(Math.floor(innerAudioContext.currentTime));
|
||
|
that.duration = innerAudioContext.duration;
|
||
|
that.durationTime = sToHs(Math.floor(innerAudioContext.duration));
|
||
|
if (!that.seek) {
|
||
|
that.current = innerAudioContext.currentTime;
|
||
|
}
|
||
|
});
|
||
|
innerAudioContext.onError(err => {
|
||
|
// console.log(err);
|
||
|
});
|
||
|
this.innerAudioContext = innerAudioContext;
|
||
|
}
|
||
|
},
|
||
|
watch: {
|
||
|
play(n) {
|
||
|
if (n) {
|
||
|
this.innerAudioContext.play();
|
||
|
} else {
|
||
|
this.innerAudioContext.pause();
|
||
|
}
|
||
|
this.$forceUpdate();
|
||
|
},
|
||
|
src() {
|
||
|
this.innerAudioContext.destroy();
|
||
|
this.contextInit();
|
||
|
}
|
||
|
},
|
||
|
created() {
|
||
|
this.contextInit();
|
||
|
},
|
||
|
beforeDestroy() {
|
||
|
this.innerAudioContext.destroy();
|
||
|
}
|
||
|
};
|
||
|
</script>
|
||
|
|
||
|
<style lang="scss">
|
||
|
.am-text-eill {
|
||
|
/*超出省略号*/
|
||
|
overflow: hidden;
|
||
|
text-overflow: ellipsis;
|
||
|
white-space: nowrap;
|
||
|
}
|
||
|
|
||
|
.audio-warp {
|
||
|
display: flex;
|
||
|
overflow: hidden;
|
||
|
height: 134upx;
|
||
|
border-radius: 10upx;
|
||
|
padding: 18upx 0 0 50upx;
|
||
|
background-color: rgba(255, 255, 255, 1);
|
||
|
}
|
||
|
.cover-warp {
|
||
|
position: relative;
|
||
|
flex-shrink: 0;
|
||
|
width: 130upx;
|
||
|
height: 100%;
|
||
|
&.hasbg {
|
||
|
background-color: #e6e6e6;
|
||
|
}
|
||
|
.cover-img {
|
||
|
width: 100%;
|
||
|
height: 100%;
|
||
|
display: none;
|
||
|
}
|
||
|
.play-btn {
|
||
|
position: absolute;
|
||
|
left: 50%;
|
||
|
top: 50%;
|
||
|
width: 80upx;
|
||
|
height: 80upx;
|
||
|
transform: translateX(-50%) translateY(-50%);
|
||
|
border-radius: 50%;
|
||
|
background-size: 100% 100%;
|
||
|
background-image: url('http://ys.tour-ma.com/r/cms/www/m/yushan/icon-nj-ztyy.png');
|
||
|
&.pause {
|
||
|
background-image: url('http://ys.tour-ma.com/r/cms/www/m/yushan/icon-nj-bfyy.png');
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
.audio-con {
|
||
|
position: relative;
|
||
|
flex: 1;
|
||
|
display: flex;
|
||
|
width: 0;
|
||
|
padding: 0 30upx;
|
||
|
align-items: center;
|
||
|
// background-color: #fcfcfc;
|
||
|
.info {
|
||
|
width: 100%;
|
||
|
}
|
||
|
.audio-title {
|
||
|
display: block;
|
||
|
padding-bottom: 14upx;
|
||
|
// padding-right: 50upx;
|
||
|
font-size: 35upx;
|
||
|
color: #000;
|
||
|
font-weight: 600;
|
||
|
}
|
||
|
.audio-author {
|
||
|
display: inline-block;
|
||
|
font-size: 24upx;
|
||
|
color: #888888;
|
||
|
width: 15%;
|
||
|
vertical-align: middle;
|
||
|
}
|
||
|
.audio-slider{
|
||
|
display: inline-block;
|
||
|
width: 74%;
|
||
|
vertical-align: middle;
|
||
|
margin: 0;
|
||
|
padding: 0 10px;
|
||
|
}
|
||
|
.audio-time {
|
||
|
position: absolute;
|
||
|
right: 30upx;
|
||
|
top: 12upx;
|
||
|
font-size: 26upx;
|
||
|
color: #9d9d9d;
|
||
|
}
|
||
|
}
|
||
|
</style>
|