123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- <template>
- <view class="audio_container">
- <view class="title-box">
- {{ title }}
- </view>
- <view>
- <slider :backgroundColor='backgroundColor' :activeColor='activeColor' @change="handleSliderChange"
- :value="sliderIndex" :max="maxSliderIndex" block-color="#C30D23" block-size="16" />
- </view>
- <view style="padding: 0px 7.5px 0px 7.5px ; display: block; ">
- <view style="float: left; font-size: 10px;color:#848484;">
- {{ currentTimeText }}
- </view>
- <view style="float: right;font-size: 10px;color:#848484;">
- {{ totalTimeText }}
- </view>
- </view>
- <view style="margin-top: 35px;">
- <view class="control">
- <view class="uni-grid-icon">
- <image @tap="handleFastRewind" src="../static/images/get-back.svg"
- style="width: 24px;height: 24px;top:3px;">
- </image>
- </view>
- <view class="uni-grid-icon">
- <image @tap="handleChangeAudioState" v-show="!isPlaying" src="../static/images/play.svg"
- style="width: 24px;height: 24px;top:3px;">
- </image>
- <image @tap="handleChangeAudioState" v-show="isPlaying" src="../static/images/pause.svg"
- style="width: 24px;height: 24px;top:3px;">
- </image>
- </view>
- <view class="uni-grid-icon">
- <image @tap="handleFastForward" src="../static/images/fast-forward.svg"
- style="width: 24px;height: 24px;top:3px;">
- </image>
- </view>
- <!-- <view class="uni-grid-icon">
- <image @tap="handleLoopPlay" src="../static/images/Loop.svg"
- style="width: 24px;height: 24px; top:3px; ">
- </image>
- </view> -->
- </view>
- </view>
- </view>
- </template>
- <script>
- export default {
- name: 'my-audio',
- //audioPlay开始播放
- //audioPause停止播放
- //audioEnd音频自然播放结束事件
- //audioCanplay音频进入可以播放状态,但不保证后面可以流畅播放
- //change播放状态改变 返回值false停止播放 true开始播放
- //audioError 播放器错误
- emits: ['audioPlay', 'audioPause', 'audioEnd', 'audioCanplay', 'change', 'audioError'],
- props: {
- title: {
- type: String
- },
- //是否自动播放
- autoplay: {
- type: Boolean,
- default: false
- },
- //滑块左侧已选择部分的线条颜色
- activeColor: {
- type: String,
- default: '#C30D23'
- },
- //滑块右侧背景条的颜色
- backgroundColor: {
- type: String,
- default: '#E5E5E5'
- },
- //音频地址
- src: {
- type: [String, Array],
- default: ''
- },
- //是否倒计时
- isCountDown: {
- type: Boolean,
- default: false
- },
- //音乐封面
- audioCover: {
- type: String,
- default: ''
- },
- //是否显示收藏按钮
- isCollectBtn: {
- type: Boolean,
- default: false
- },
- //是否显示分享按钮
- isShareBtn: {
- type: Boolean,
- default: false
- },
- },
- data() {
- return {
- totalTimeText: '00:00', //视频总长度文字
- currentTimeText: '00:00:00', //视频已播放长度文字
- isPlaying: false, //播放状态
- sliderIndex: 0, //滑块当前值
- maxSliderIndex: 100, //滑块最大值
- IsReadyPlay: false, //是否已经准备好可以播放了
- isLoop: false, //是否循环播放
- speedValue: [0.5, 0.8, 1.0, 1.25, 1.5, 2.0],
- speedValueIndex: 2,
- playSpeed: '1.0', //播放倍速 可取值:0.5/0.8/1.0/1.25/1.5/2.0
- stringObject: (data) => {
- return typeof (data)
- },
- innerAudioContext: uni.createInnerAudioContext()
- }
- },
- async mounted() {
- this.innerAudioContext.src = typeof (this.src) == 'string' ? this.src : this.src[0];
- if (this.autoplay) {
- if (!this.src) return console.error('src cannot be empty,The target value is string or array')
- // #ifdef H5
- var ua = window.navigator.userAgent.toLowerCase();
- if (ua.match(/MicroMessenger/i) == 'micromessenger') {
- const jweixin = require('../utils/jweixin');
- jweixin.config({});
- jweixin.ready(() => {
- WeixinJSBridge.invoke('getNetworkType', {}, (e) => {
- this.innerAudioContext.play();
- })
- })
- }
- // #endif
- // #ifndef H5
- this.innerAudioContext.autoplay = true;
- // #endif
- }
- //音频播放事件
- this.innerAudioContext.onPlay(() => {
- this.isPlaying = true;
- this.$emit('audioPlay')
- this.$emit('change', {
- state: true
- });
- setTimeout(() => {
- this.maxSliderIndex = parseFloat(this.innerAudioContext.duration).toFixed(2);
- }, 100)
- });
- //音频暂停事件
- this.innerAudioContext.onPause(() => {
- this.$emit('audioPause');
- this.$emit('change', {
- state: false
- });
- });
- //音频自然播放结束事件
- this.innerAudioContext.onEnded(() => {
- this.isPlaying = !this.isPlaying;
- this.$emit('audioEnd');
- if (this.isLoop) {
- this.changePlayProgress(0);
- this.innerAudioContext.play();
- }
- });
- //音频进入可以播放状态,但不保证后面可以流畅播放
- this.innerAudioContext.onCanplay((event) => {
- this.IsReadyPlay = true;
- this.$emit('audioCanplay');
- let duration = this.innerAudioContext.duration;
- //console.log('总时长', duration)
- //将当前音频长度秒转换为00:00:00格式
- this.totalTimeText = this.getFormateTime(duration);
- this.maxSliderIndex = parseFloat(duration).toFixed(2);
- //console.log(this.getFormateTime(duration))
- //console.log('总时长1', this.totalTimeText)
- //防止视频无法正确获取时长
- setTimeout(() => {
- duration = this.innerAudioContext.duration;
- //将当前音频长度秒转换为00:00:00格式
- this.totalTimeText = this.getFormateTime(duration);
- this.maxSliderIndex = parseFloat(duration).toFixed(2);
- //console.log('总时长2', this.totalTimeText)
- }, 300)
- });
- //音频播放错误事件
- this.innerAudioContext.onTimeUpdate((res) => {
- this.sliderIndex = parseFloat(this.innerAudioContext.currentTime).toFixed(2);
- this.currentTimeText = this.getFormateTime(this.innerAudioContext.currentTime);
- });
- //音频播放错误事件
- this.innerAudioContext.onError((res) => {
- console.log(res.errMsg);
- console.log(res.errCode);
- this.$emit('change', {
- state: false
- });
- this.audioPause();
- this.$emit('audioError', res);
- });
- },
- methods: {
- //销毁innerAudioContext()实例
- audioDestroy() {
- if (this.innerAudioContext) {
- this.innerAudioContext.destroy();
- this.isPlaying = false;
- }
- },
- //点击变更播放状态
- handleChangeAudioState() {
- if (this.isPlaying && !this.innerAudioContext.paused) {
- this.audioPause();
- } else {
- this.audioPlay();
- }
- },
- //开始播放
- audioPlay() {
- this.innerAudioContext.play();
- this.isPlaying = true;
- },
- //暂停播放
- audioPause() {
- this.innerAudioContext.pause();
- this.isPlaying = false;
- },
- //变更滑块位置
- handleSliderChange(e) {
- this.changePlayProgress(e.detail ? e.detail.value : e)
- },
- //更改播放倍速
- handleChageSpeed() {
- //获取播放倍速列表长度
- let speedCount = this.speedValue.length;
- //如果当前是最大倍速,从-1开始
- if (this.speedValueIndex == (speedCount - 1)) {
- this.speedValueIndex = -1;
- }
- //最新倍速序号
- this.speedValueIndex += 1;
- //获取最新倍速文字
- this.playSpeed = this.speedValue[this.speedValueIndex].toFixed(1);
- //暂停播放
- this.audioPause();
- //变更播放倍速
- this.innerAudioContext.playbackRate(this.speedValue[this.speedValueIndex]);
- //开始播放
- this.audioPlay();
- },
- //快退15秒
- handleFastRewind() {
- if (this.IsReadyPlay) {
- let value = parseInt(this.sliderIndex) - 15;
- this.changePlayProgress(value >= 0 ? value : 0);
- }
- },
- //快进15秒
- handleFastForward() {
- if (this.IsReadyPlay) {
- let value = parseInt(this.sliderIndex) + 15;
- this.changePlayProgress(value <= this.innerAudioContext.duration ? value : this.innerAudioContext
- .duration);
- }
- },
- //开启循环播放
- handleLoopPlay() {
- this.isLoop = !this.isLoop;
- if (this.isLoop) {
- uni.showToast({
- title: '已开启循环播放',
- duration: 1000
- });
- } else {
- uni.showToast({
- title: '取消循环播放',
- duration: 1000
- });
- }
- },
- //更改播放进度
- changePlayProgress(value) {
- this.innerAudioContext.seek(value);
- this.sliderIndex = value;
- this.currentTimeText = this.getFormateTime(value);
- },
- //秒转换为00:00:00
- getFormateTime(time) {
- let ms = time * 1000; // 1485000毫秒
- let date = new Date(ms);
- // 注意这里是使用的getUTCHours()方法,转换成UTC(协调世界时)时间的小时
- let hour = date.getUTCHours();
- // let hour = date.getHours(); 如果直接使用getHours()方法,则得到的时分秒格式会多出来8个小时(在国内开发基本都是使用的是东八区时间),getHours()方法会把当前的时区给加上。
- let minute = date.getMinutes();
- let second = date.getSeconds();
- let formatTime =
- `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}:${second.toString().padStart(2, '0')}`;
- return formatTime;
- },
- handleCollec() {
- this.$emit('audioCollec');
- },
- handleShare() {
- this.$emit('audioShare');
- },
- },
- onUnload() {
- this.audioDestroy()
- },
- onHide() {
- this.audioDestroy()
- },
- beforeDestroy() {
- this.audioDestroy()
- }
- }
- </script>
- <style lang="scss" scoped>
- .control {
- display: flex;
- justify-content: space-around;
- padding: 0 30px;
- box-sizing: border-box;
- }
- .audio_container {
- box-shadow: 0 0 5px #c3c3c3;
- padding: 15px 10px 15px 10px;
- .audio-title {
- font-size: 14px;
- }
- .uni-noticebar {
- padding: 0px;
- padding-right: 25px;
- margin-bottom: 0px;
- display: inline-block;
- }
- .audio-subTitle {
- width: 100%;
- text-align: left;
- font-size: 20px;
- color: blue;
- }
- .speed-text {
- position: absolute;
- top: 0px;
- left: 15px;
- right: 0;
- color: #475266;
- font-size: 8px;
- font-weight: 600;
- }
- .uni-grid-icon {
- text-align: center;
- }
- }
- </style>
|