uniapp音频播放组件,兼容微信小程序、h5等,可倍数播放,快进快退,切换上下音频等

<template>

  <!--父组件-->

  <view>

    <cxAdudioPlay

      :list="list"

      :BsNav="BsNav"

      :autoplays="true"

      :slideYes="true"

      :autoNext="true"

      :switAud="true"

    ></cxAdudioPlay>

  </view>

</template>

<script>

/*

     list      --   音频文件传入 不传无法播放/数组形式

     Faskms    --   快进秒数 number 默认15秒

     Slowms    --   快退秒数 number 默认15秒

     autoNext  --   是否自动播放下一首

     autoplays --   进入页面是否自动播放 - 默认false

     slideYes  --   滑动进度条时是否开启播放 - 默认false

     switAud   --   切换上下音频是否开启播放 - 默认false

     BsNav     --   倍数数据传入/数组形式

     

     按钮图片未自定义,如想改动请在组件内部修改,页面头部已注释 -- 逻辑根据自己需求改

     目前只测试 微信小程序和H5和APP -- 其他平台未知

     Author:chenxin  交流vx:cxalq8-24  

    */

import cxAdudioPlay from "../components/le-audio.vue";

export default {

  components: {

    cxAdudioPlay,

  },

  data() {

    return {

      list: [

        //音频文件

        {

          recorPath:

            "https://audio.yuntuys.com/2021-03-31/audio/be52ad3e45ce412d8d27b2b9f21016c4.mp3?sign=8de5094268e7a6375b54e79b08a1f2b3&t=6528efe6",

        },

        {

          recorPath:

            "https://audio.yuntuys.com/2021-03-31/audio/3515a61a229042778fe6f2fa38dd9025.mp3?sign=79d073208c20eec367ae984ea92711a9&t=6528eff7",

        },

        {

          recorPath:

            "https://audio.yuntuys.com/2021-03-31/audio/15c84381ec9a4cb5a8c7f0f803436d0a.mp3?sign=36a4ab5ec2387343795ad1d0b1b82dce&t=6528f008",

        },

      ],

      BsNav: [

        //倍数-自定义

        {

          id: 1.0,

          bs: "1.0",

        },

        {

          id: 1.5,

          bs: "1.5",

        },

        {

          id: 2.0,

          bs: "2.0",

        },

      ],

    };

  },

  methods: {},

};

</script>

<style>

</style>

音频组件

<template>

  <!--音频组件-->

  <view>

    <view class="bgfff">

      <view>

        <view class="audo-video">

          <!--音频播放按钮处-->

          <view class="audo-top">

            <!--上一首切换按钮-->

            <image

              v-if="jian"

              style="width: 50rpx; height: 50rpx"

              @click="nosig"

              src="/static/sys.png"

              mode="aspectFill"

            ></image>

            <image

              v-else

              @click="sig"

              src="/static/xys.png"

              style="width: 50rpx; height: 50rpx; transform: rotate(180deg)"

              mode="aspectFill"

            ></image>

            <!--上一首切换按钮-->

            <!--快退按钮-->

            <image

              src="/static/kt.png"

              style="width: 45rpx; height: 45rpx"

              mode="aspectFill"

              @click="kt()"

            ></image>

            <!--快退按钮-->

            <!--播放按钮-->

            <image

              :src="succes ? '/static/bofang2.png' : '/static/zt.png'"

              mode="aspectFill"

              style="width: 180rpx; height: 180rpx"

              @click="plays()"

            ></image>

            <!--播放按钮-->

            <!--快进按钮-->

            <image

              src="/static/kj.png"

              style="width: 45rpx; height: 45rpx"

              mode="aspectFill"

              @click="kj()"

            ></image>

            <!--快进按钮-->

            <!--下一首切换按钮-->

            <image

              v-if="jia"

              @click="noxig"

              style="width: 50rpx; height: 50rpx; transform: rotate(180deg)"

              src="/static/sys.png"

              mode="aspectFill"

            >

            </image>

            <image

              v-else

              style="width: 50rpx; height: 50rpx"

              src="/static/xys.png"

              @click="xig"

              mode="aspectFill"

            ></image>

            <!--下一首切换按钮-->

          </view>

          <!--音频播放按钮处-->

          <!--音频api处[视频代替音频-实现倍数功能]-->

          <video

            id="myVideo"

            ref="myVideo"

            :src="recorPath"

            class="hidden"

            @timeupdate="timeupdate"

            :autoplay="autoplays"

            @loadedmetadata="loadedmetadata"

            @ended="next"

            controls

            style="width: 10rpx; height: 10rpx"

          ></video>

          <!--音频api处[视频代替音频-实现倍数功能]-->

          <view class="audo-a" style="margin: 0 auto">

            <!--进度条-->

            <view class="slider-box">

              <text class="mm">{{ timer }}</text>

              <slider

                style="width: 370rpx"

                @change="sliderChange"

                @changing="sliderChanging"

                class="audio-slider"

                block-size="16"

                :min="0"

                :max="duration"

                :value="currentTime"

                activeColor="#FFA929"

                @touchstart="lock = true"

                @touchend="lock = false"

              />

              <text class="ss" v-if="overTimer != 'NaN:NaN'">{{

                overTimer

              }}</text>

              <text class="ss" v-else>00.00</text>

            </view>

            <!--进度条-->

            <!--倍数-->

            <view

              class="beishu"

              style="border: 3rpx solid #c8c9cc"

              @click="beishu"

              >{{ BsNav[bsindex].bs }} X

            </view>

            <view class="absolute" style="right: 0; top: 80rpx" v-if="shows">

              <!--  <u-transition :show="show" mode="slide-right" duration="300"> -->

              <view

                class="beishu-a"

                style="border: 2rpx solid #c8c9cc"

                v-if="show"

              >

                <view

                  v-for="(item, index) in BsNav"

                  :key="index"

                  @click="setRate(index, item)"

                  class="title"

                  :style="{ color: bsid == item.id ? '#8D48FE' : '' }"

                >

                  {{ item.bs }} X

                </view>

              </view>

              <!--  </u-transition> -->

            </view>

            <!--倍数-->

          </view>

        </view>

      </view>

    </view>

    <view class="h-100"></view>

    <!--占位-->

  </view>

  <!--音频组件 Author:chenxin-->

</template>

<script>

/*

     list      --   音频文件传入 不传无法播放/数组形式

     Faskms    --   快进秒数 number 默认15秒

     Slowms    --   快退秒数 number 默认15秒

     autoNext  --   是否自动播放下一首

     autoplays --   进入页面是否自动播放 - 默认false

     slideYes  --   滑动进度条时是否开启播放 - 默认false

     switAud   --   切换上下音频是否开启播放 - 默认false

     BsNav     --   倍数数据传入/数组形式

     

     按钮图片未自定义,如想改动请在组件内部修改,页面头部已注释 -- 逻辑根据自己需求改

     目前只测试 微信小程序和H5和APP -- 其他平台未知

      Author:chenxin  交流vx:cxalq8-24  

    */

export default {

  name: "cx-audio-play",

  props: {

    list: {

      //音频数据

      Type: Array,

      default: () => [],

    },

    Faskms: {

      //快进秒数

      Type: Number,

      default: 15,

    },

    Slowms: {

      //快退秒数

      Type: Number,

      default: 15,

    },

    autoNext: {

      Type: Boolean,

      default: false,

    },

    autoplays: {

      //是否开启自动播放

      Type: Boolean,

      default: false,

    },

    slideYes: {

      //滑动进度条 - 是否开启播放

      Type: Boolean,

      default: false,

    },

    switAud: {

      Type: Boolean, //切换上下音频 - 是否开启播放

      default: false,

    },

    BsNav: {

      //倍数-传入

      Type: Array,

      default: () => [

        {

          id: 1.0,

          bs: "1.0",

        },

        {

          id: 1.5,

          bs: "1.5",

        },

        {

          id: 2.0,

          bs: "2.0",

        },

      ],

    },

  },

  data() {

    return {

      shows: false, //倍数弹框

      show: true, //倍数弹框动画默认开启

      jian: true, //减-切换图标

      jia: true, //加-切换图标

      succes: false, //播放按钮

      bsid: "", //倍数默认显示第一个

      bsindex: 0, //倍数默认显示第一个

      num: 0,

      current: 0, //当前选中的索引

      recorPath: "", //音频播放地址

      lock: false, // 锁

      currentTime: 0, //当前进度

      duration: 100, // 总进度

      videoContext: null,

      loading: true, //锁 加载

    };

  },

  onReady() {},

  onShow() {},

  mounted() {

    this.videoContext = uni.createVideoContext("myVideo", this);

    //默认播放第一个 -- 按钮展示

    if (this.list.length != 0) {

      this.recorPath = this.list[0].recorPath;

      this.$nextTick(() => {

        this.videoContext.play();

      });

      if (this.list.length > 1) {

        //音频文件大于1 -- 下一个切换默认显示

        this.jia = false;

        if (this.autoplays) {

          this.succes = true;

        }

      }

    }

    //倍数默认处理

    if (this.BsNav.length != 0) {

      this.bsid = this.BsNav[0].id;

      this.$nextTick(() => {

        //#ifdef H5

        this.$refs.myVideo.playbackRate(this.bsid);

        //#endif

        //#ifndef H5

        this.videoContext.playbackRate(this.bsid);

        //#endif

      });

    }

  },

  updated() {},

  onLoad() {},

  onHide() {

    //监听页面离开 - 销毁音频

    //#ifdef H5

    this.$refs.myVideo.stop();

    //#endif

    //#ifndef H5

    this.videoContext.stop();

    //#endif

  },

  onUnload() {

    //监听页面卸载 - 销毁音频

    //#ifdef H5

    this.$refs.myVideo.stop();

    //#endif

    //#ifndef H5

    this.videoContext.stop();

    //#endif

  },

  destroyed() {

    // this.innerAudioContext.stop();

  },

  computed: {

    timer() {

      return calcTimer(this.currentTime);

    },

    overTimer() {

      return calcTimer(this.duration);

    },

  },

  watch: {},

  methods: {

    plays() {

      //播放暂停

      if (!this.list || this.list.length == 0) {

        console.log("暂无音频数据~");

        return;

      }

      this.playloading();

      this.succes = !this.succes;

      if (this.succes) {

        // this.currentTime = 0

        // console.log('-----------------')

        //#ifdef H5

        this.$refs.myVideo.play();

        //#endif

        //#ifndef H5

        this.videoContext.play();

        //#endif

      } else {

        uni.hideLoading();

        //#ifdef H5

        this.$refs.myVideo.pause();

        //#endif

        //#ifndef H5

        this.videoContext.pause();

        //#endif

      }

    },

    beishu() {

      //倍速弹框

      this.shows = !this.shows;

    },

    // 倍速

    setRate(index, item) {

      this.bsid = item.id;

      this.bsindex = index;

      this.shows = false;

      //#ifdef H5

      this.$refs.myVideo.playbackRate(item.id);

      //#endif

      //#ifndef H5

      this.videoContext.playbackRate(item.id);

      //#endif

    },

    // 更新进度条

    timeupdate(event) {

      if (this.lock) return; // 锁

      var currentTime, duration;

      if (event.detail.detail) {

        currentTime = event.detail.detail.currentTime;

        duration = event.detail.detail.duration;

      } else {

        currentTime = event.detail.currentTime;

        duration = event.detail.duration;

      }

      this.currentTime = currentTime;

      this.duration = duration;

    },

    // 拖动进度条

    sliderChange(data) {

      //此处滑动进度条--开始播放

      if (this.slideYes && !this.succes) {

        //#ifdef H5

        this.$refs.myVideo.play();

        //#endif

        //#ifndef H5

        this.videoContext.play();

        //#endif

        this.succes = true;

      }

      //#ifdef H5

      this.$refs.myVideo.seek(data.detail.value); //获取秒数

      //#endif

      //#ifndef H5

      this.videoContext.seek(data.detail.value); //获取秒数

      //#endif

    },

    //拖动中

    sliderChanging(data) {

      if (data.detail.value == 0) {

        this.succes = false;

        //#ifdef H5

        this.$refs.myVideo.pause();

        //#endif

        //#ifndef H5

        this.videoContext.pause();

        //#endif

      }

      this.currentTime = data.detail.value;

    },

    // 视频加载完成

    loadedmetadata(data) {

      this.duration = data.detail.duration;

    },

    sig() {

      //上一首

      if (!this.list || this.list.length == 0) {

        console.log("暂无音频数据~");

        return;

      }

      this.num -= 1;

      if (this.num < this.list.length) {

        this.loading = true;

        this.playloading(); //加载框

      }

      if (this.num + 1 < this.list.length && this.num + 1 != 1) {

        //点击上一首小于音频数据总长度

        this.jia = false; // 下按钮-亮且可点击

        this.jian = false; // 上按钮-亮且可点击

      } else {

        this.jian = true; // 上按钮-灰且阻止

        this.jia = false; // 下按钮-亮且可点击

      }

      this.recorPath = this.list[this.num].recorPath;

      if (this.switAud) {

        //切换时是否默认开启播放

        this.succes = true;

        setTimeout(() => {

          //#ifdef H5

          this.$refs.myVideo.play();

          //#endif

          //#ifndef H5

          this.videoContext.play();

          //#endif

        }, 100);

      } else {

        this.succes = false;

      }

    },

    xig() {

      //下一首

      if (!this.list || this.list.length == 0) {

        console.log("暂无音频数据~");

        return;

      }

      this.num += 1;

      if (this.num < this.list.length) {

        this.loading = true;

        this.playloading(); //加载框

      }

      if (this.num + 1 < this.list.length) {

        //点击下一首小于音频数据总长度

        this.jia = false; // 下按钮-亮且可点击

        this.jian = false; // 上按钮-亮且可点击

      } else {

        //大于总长度

        this.jia = true; //下按钮 - 灰且阻止

        this.jian = false; //上按钮 - 亮可点击

      }

      this.recorPath = this.list[this.num].recorPath;

      if (this.switAud) {

        //切换时是否默认开启播放

        this.succes = true;

        setTimeout(() => {

          //#ifdef H5

          this.$refs.myVideo.play();

          //#endif

          //#ifndef H5

          this.videoContext.play();

          //#endif

        }, 100);

      } else {

        this.succes = false;

      }

    },

    nosig() {

      uni.showToast({

        title: "到头了~",

        icon: "none",

      });

    },

    noxig() {

      uni.showToast({

        title: "没有更多了~",

        icon: "none",

      });

    },

    kt() {

      //快退

      if (!this.list || this.list.length == 0) {

        console.log("暂无音频数据~");

        return;

      }

      let a = (this.currentTime - Math.floor(15 % 60)).toFixed(0); //当前时间-15秒

      if (a < 1) {

        this.succes = false;

        //#ifdef H5

        this.$refs.myVideo.pause();

        //#endif

        //#ifndef H5

        this.videoContext.pause();

        //#endif

      }

      //#ifdef H5

      this.$refs.myVideo.seek(a);

      //#endif

      //#ifndef H5

      this.videoContext.seek(a);

      //#endif

    },

    kj() {

      //快进

      if (!this.list || this.list.length == 0) {

        console.log("暂无音频数据~");

        return;

      }

      let a = (this.currentTime + Math.floor(15 % 60)).toFixed(0); //当前时间+15秒

      //#ifdef H5

      this.$refs.myVideo.seek(a);

      //#endif

      //#ifndef H5

      this.videoContext.seek(a);

      //#endif

    },

    next(data) {

      //监听音频结束

      this.succes = false;

      /*音频结束--是否自动播放下一首*/

      if (!this.autoNext) {

        return;

      }

      if (this.num + 1 < this.list.length) {

        this.succes = true;

        this.num += 1;

        this.recorPath = this.list[this.num].recorPath;

        setTimeout(() => {

          //#ifdef H5

          this.$refs.myVideo.play();

          //#endif

          //#ifndef H5

          this.videoContext.play();

          //#endif

        }, 100);

      } else {

        this.jia = true; //下按钮 - 灰且阻止

        this.jian = false; //上按钮 - 亮可点击

      }

      // console.log('音频结束-------')

    },

    playloading() {

      //加载框--封

      if (this.loading) {

        uni.showLoading({

          title: "音频缓存中...",

        });

        this.loading = false;

      }

      setTimeout(() => {

        uni.hideLoading();

      }, 1600);

    },

  },

  watch: {},

};

//时间换算

function calcTimer(timer) {

  if (timer === 0 || typeof timer !== "number") {

    return "00:00";

  }

  let mm = Math.floor(timer / 60);

  let ss = Math.floor(timer % 60);

  if (mm < 10) {

    mm = "0" + mm;

  }

  if (ss < 10) {

    ss = "0" + ss;

  }

  return mm + ":" + ss;

}

</script>

<style lang="scss" scoped>

page {

  background-color: #f6f6f8;

}

/*  #video {

        width: 100%;

    } */

.audo-video {

  padding-bottom: 20rpx;

  color: #999;

}

.slider-box {

  display: flex;

  align-items: center;

  justify-content: center;

  font-size: 27rpx;

  color: #999;

}

button {

  display: inline-block;

  width: 100rpx;

  background-color: #fff;

  font-size: 24rpx;

  color: #000;

  padding: 0;

}

.hidden {

  position: fixed;

  top: 0;

  left: -10rpx;

  z-index: -1;

  width: 1rpx;

  height: 1rpx;

}

.audo-top {

  padding: 20rpx 40rpx;

  display: flex;

  justify-content: space-around;

  align-items: center;

  image {

    width: 45rpx;

    height: 45rpx;

  }

}

.audo-a {

  display: flex;

  justify-content: space-between;

  align-items: center;

  width: 700rpx;

  position: relative;

  z-index: 9;

}

.beishu {

  position: relative;

  width: 100rpx;

  padding-top: 5rpx;

  padding-bottom: 5rpx;

  text-align: center;

  border-radius: 25rpx;

  font-size: 28rpx;

}

.absolute {

  position: absolute;

  .beishu-a {

    width: 200rpx;

    border-radius: 20rpx;

    text-align: center;

    line-height: 90rpx;

    background: #fff;

    .title {

      pdding-left: 30rpx;

    }

  }

}

</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值