微信小程序自定义播放器

当微信小程序官方提供的 audio 组件样式不满足我们的需求时,我们可以自定义一个音频播放器,由于不可抗力原因,我用uView框架中的 Popup 弹出层 实现了一个音频播放器弹框,大家根据需求做参考就好啦,话不多说,直接看效果吧~

1、效果图:暂停&播放

    

2、具体实现

 2.1 准备按钮图片

2.2 使用组件

ps:下面代码中用到的示例mp3文件地址是从网上随便找的,如有侵权联系我删除,谢谢。

<template>
  <MyAudio ref="myAudio" :show.sync="showAudio"/>
</template>

<script>
import MyAudio from "@/components/MyAudio";
export default {
  components: {
    MyAudio
  },
  data() {
    return {
      showAudio: false,
      path: 'http://music.163.com/song/media/outer/url?id=447925558.mp3'
    }
  },
  onLoad(options) {
    this.showAudio = true
    this.$refs.myAudio.init(this.path)
  }
}
</script>
2.3 封装MyAudio组件
2.3.1 MyAudio.vue 文件
<template>
  <u-popup
    :show="show"
    mode="center"
    :closeable="true"
    :safeAreaInsetBottom="false"
    round="16rpx"
    @close="clickMask"
  >
    <view class="audioPopup">
      <view class="audioWra">
        <view class="info">
          <view class="title">音频播放器</view>
          <view class="my_audio_content">
            <AudioPlayer
              ref="audioplayer"
              startPic="https://img-blog.csdnimg.cn/direct/9a3eb3af5f2e466cb24acef01d684be3.png"
              endPic="https://img-blog.csdnimg.cn/direct/ab1d7719ed024235af8144213cafa8bb.png"
            ></AudioPlayer>
          </view>
          <view class="audioBtnWra">
            <view class="left" @click="close">关闭</view>
          </view>
        </view>
      </view>
    </view>
  </u-popup>
</template>
<script>
import AudioPlayer from "./AudioPlayer";
export default {
  components: {
    AudioPlayer,
  },
  props: {
    show: {
      type: Boolean,
      default: false,
    },
    isMaskClose: {
      type: Boolean,
      default: true,
    },
    isMove: {
      type: Boolean,
      default: false,
    },
  },
  methods: {
    init(monitorFileName) {
      this.$refs.audioplayer.init(monitorFileName);
    },
    clickMask() {
      if (!this.isMaskClose) return;
      this.close();
    },
    close() {
      this.$refs.audioplayer.refresh();
      this.$emit("update:show", false);
    },
  },
};
</script>
<style scoped>
.mask {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  opacity: 0;
  background-color: rgba(0, 0, 0, 0.6);
  z-index: -1;
  transition: all 0.3s ease-in-out 0s;
}
.mask-show {
  z-index: 1000;
  opacity: 1;
}
.audioPopup .audioWra {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 9999;
}
.audioPopup .audioWra .info {
  background: #ffffff;
  width: 560rpx;
  opacity: 1;
  background: #ffffff;
  border-radius: 16rpx;
  animation: slide-scaer 0.2s linear;
  padding-top: 24rpx;
  box-sizing: border-box;
}
.audioPopup .audioWra .info .title {
  font-size: 32rpx;
  font-family: PingFangSC, PingFangSC-Medium;
  font-weight: 500;
  text-align: left;
  color: #585858;
  padding: 0rpx 24rpx;
  text-align: center;
}
.audioPopup .audioWra .info .audioBtnWra {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 100rpx;
  line-height: 100rpx;
  font-weight: 400;
}
.audioPopup .audioWra .info .audioBtnWra .left {
  flex: 1;
  color: #aaaaaa;
  font-size: 28rpx;
  height: 100%;
  text-align: center;
}
.audioPopup .audioWra .info .audioBtnWra .right {
  flex: 1;
  color: #4088fe;
  font-size: 28rpx;
  height: 100%;
  text-align: center;
}
@keyframes slide-scaer {
  from {
    transform: scale(0);
  }
  to {
    transform: scale(1);
  }
}
.my_audio_content {
  padding: 50rpx 24rpx 30rpx;
}
</style>
2.3.2 AudioPlayer.vue 文件
<template>
  <!-- 音频播放器组件 -->
  <view class="my-audio">
    <image
      class="audio-btn"
      @click="doPause"
      :src="startPic"
      v-if="!status"
    ></image>
    <image
      class="audio-btn"
      @click="doPlay"
      :src="endPic"
      v-if="status"
    ></image>
    <view style="flex: 1">
      <slider
        @change="changeAudio"
        class="audio-slider"
        activeColor="#1790FF"
        backgroundColor="#CDE5FF"
        block-color="#1790FF"
        blockSize="10"
        :min="0"
        :max="duration.toFixed(0)"
        :value="currentTime.toFixed(0)"
        :step="0.1"
      ></slider>
    </view>
    <view class="audio-time">
      <span class="audio-current">{{ getTime(Math.round(currentTime)) }}</span>
      <span class="audio-duration">/{{ getTime(Math.round(duration)) }}</span>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      // url: null,
      context: null,
      currentTime: 0,
      duration: 0,
      status: false,
    };
  },
  props: {
    startPic: String,
    endPic: String,
    audioId: [String, Number],
  },
  methods: {
    init(monitorFileName) {
      this.context = uni.createInnerAudioContext();
      this.context.src = monitorFileName;
      this.onTimeUpdate();
      this.onCanplay();
      this.onEnded();
      uni.$on("stop", (id) => {
        if (id && id != this.audioId) {
          this.context.stop();
          this.status = false;
        } else if (!id) {
          this.context.stop();
          this.status = false;
        }
      });
    },
    // 点击播放
    doPlay() {
      this.context.pause();
      this.status = !this.status;
    },
    // 点击暂停
    doPause() {
      this.context.play();
      this.status = !this.status;
    },
    // 进入可播放状态
    onCanplay() {
      this.context.onCanplay(() => {
        var times = setInterval(() => {
          this.duration = this.context.duration;
          console.log(this.duration);
          if (this.context.duration != 0) {
            clearInterval(times);
          }
        }, 500);
      });
    },
    // 音频播放进度
    onTimeUpdate() {
      this.context.onTimeUpdate(() => {
        if (!Number.isFinite(this.context.duration)) {
          this.duration = this.context.currentTime + 10;
          this.currentTime = this.context.currentTime;
        } else {
          this.duration = this.context.duration;
          this.currentTime = this.context.currentTime;
        }
      });
    },
    // 播放结束
    onEnded() {
      this.context.onEnded(() => {
        this.status = false;
        this.currentTime = 0;
      });
    },
    changeAudio(e) {
      let paused = this.context.paused;
      this.context.pause();
      this.context.seek(e.detail.value);
      this.currentTime = e.detail.value;
      if (!paused) {
        this.context.play();
      }
    },
    // 音频播放时间换算
    getTime(time) {
      var duration = parseInt(time);
      var minute = parseInt(duration / 60);
      var sec = (duration % 60) + "";
      var isM0 = ":";
      if (minute === 0) {
        minute = "00";
      } else if (minute < 10) {
        minute = "0" + minute;
      }
      if (sec.length === 1) {
        sec = "0" + sec;
      }
      return minute + isM0 + sec;
    },
    towNum(num) {
      if (num >= 10) {
        return num;
      } else {
        return "0" + num;
      }
    },
    // 关闭时调用
    refresh() {
      this.status = false;
      this.currentTime = 0;
      this.context.stop();
    },
  },
};
</script>

<style lang="scss" scoped>
.my-audio {
  width: 100%;
  height: 96rpx;
  background: #f0f7ff;
  border-radius: 8rpx;
  padding: 0 14rpx;
  box-sizing: border-box;
  display: flex;
  align-items: center;
}
.audio-btn {
  width: 60rpx;
  height: 60rpx;
}
.audio-time {
  font-size: 24rpx;
}
.audio-current {
  color: #424b59;
}
.audio-duration {
  color: #999999;
}
</style>

  • 30
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值