<template>
  <div class="container">
    <!-- 进度条 -->
    <div class="progress-bar">
      <div class="tab-player-progress">
        <div class="_progress-text">
          <!-- 播放秒数 -->
          <span class="timer">{{ audio.currentTime | formatSecond }}</span>
          <!-- 总秒数 -->
          <span class="timers">{{ datas.duration | formatSecond }}</span>
        </div>
        <!-- 进度条 -->
        <div class="p_slider" @touchstart="handleTouchStart">
          <div class="p_slider_track"></div>
          <div class="p_slider_fill" :style="'width:' + sliderTime + '%'"></div>
          <div class="p-box" :style="'left:' + sliderTime + '%'">
            <div class="p_slider_thumb"></div>
            <div class="p_slider_thumbs"></div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
// 将整数转换成 时:分:秒的格式
function realFormatSecond(second) {
  var secondType = typeof second;

  if (secondType === "number" || secondType === "string") {
    second = parseInt(second);
    var mimute = Math.floor(second / 60);
    second = second - mimute * 60;

    return ("0" + mimute).slice(-2) + ":" + ("0" + second).slice(-2);
  } else {
    return "00:00";
  }
}
export default {
  filters: {
    // 将整数转化成时分秒
    formatSecond(second = 0) {
      return realFormatSecond(second);
    },
  },
  data() {
    return {
      datas: {
        fileUrl: "", //音频地址
        duration: "", //时长
        createTime: "",
      },
      audio: {
        playing: false, // 该字段是音频是否处于播放状态的属性
        currentTime: 0, // 音频当前播放时长
        minTime: 0,
        step: 0.1,
      },
      audioKey: 0,
      sliderTime: 0, //滑动进度时间
    };
  },
  computed: {},
  watch: {},
  created() {},
  mounted() {},
  methods: {
    // touchstart	触摸开始,多点触控,后面的手指同样会触发
    // touchmove	接触点改变,滑动时
    // touchend	触摸结束,手指离开屏幕时
    // touchcancel	触摸被取消,当系统停止跟踪触摸的时候触发
    handleTouchStart(e) {
      this.setValue(e.touches[0]);
      document.addEventListener("touchmove", this.handleTouchMove); //移动
      document.addEventListener("touchup", this.handleTouchEnd); //
      document.addEventListener("touchend", this.handleTouchEnd); //抬起
      document.addEventListener("touchcancel", this.handleTouchEnd);
    },
    handleTouchMove(e) {
      this.setValue(e.changedTouches[0]);
    },
    handleTouchEnd(e) {
      this.setValue(e.changedTouches[0]);
      document.removeEventListener("touchmove", this.handleTouchMove);
      document.removeEventListener("touchup", this.handleTouchEnd);
      document.removeEventListener("touchend", this.handleTouchEnd);
      document.removeEventListener("touchcancel", this.handleTouchEnd);
    },
    // 托拽更新进度条从点击位置更新 value
    setValue(e) {
      const $el = this.$el;
      const { minTime, step } = this.audio;
      const { duration } = this.datas;
      // Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。
      let value =
        ((e.clientX - $el.getBoundingClientRect().left) / $el.offsetWidth) *
        (duration - minTime);
      // console.log(value,'value');
      value = Math.round(value / step) * step + minTime;
      value = parseFloat(value.toFixed(5));
      if (value > duration) {
        value = duration;
      } else if (value < minTime) {
        value = minTime;
      }
      this.$refs.audio.currentTime = value;
    },
    // 拖动进度条,改变当前时间
    changeCurrentTime(index) {
      this.$refs.audio.currentTime = parseInt(
        (index / 100) * this.datas.duration
      );
    },
  },
};
</script>
<style scoped lang="less">
.progress-bar {
  position: relative;
  width: 100%;
  height: 120px;
  margin: 0px auto;
  margin-top: 80px;
  text-align: center;
}
.timer {
  vertical-align: sub;
  font-size: 20px;
  font-family: PingFang SC;
  font-weight: 500;
  color: #b1b1b1;
  position: absolute;
  left: 20px;
  top: 0;
  transform: translateY(-50%);
}
.timers {
  vertical-align: sub;
  font-size: 20px;
  font-family: PingFang SC;
  font-weight: 500;
  color: #b1b1b1;
  position: absolute;
  right: 20px;
  top: 0;
  transform: translateY(-50%);
}
// 进度条
.p_slider {
  width: 70%;
  margin: 0px auto;
  position: relative;
  // height: 24px;
  display: flex;
  align-items: center;
  cursor: default;
  user-select: none;
  outline: none;
}
.p_slider_track {
  position: absolute;
  height: 5px;
  left: 0;
  right: 0;
  top: 50%;
  margin-top: -1px;
  background-color: #f2f2f2;
}
.p_slider_fill {
  position: absolute;
  height: 5px;
  width: 100%;
  background-color: #ff821e;
  left: 0;
  top: 50%;
  margin-top: -1px;
}
.p-box {
  position: relative;
  width: 100px;
  height: 100px;
  margin-top: -100px;
}
.p_slider_thumb {
  position: absolute;
  top: 100%;
  width: 15px;
  height: 15px;
  background-color: #fff;
  color: #ff821e;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  cursor: pointer;
  border: 4px solid #ff821e;
}
.p_slider_thumbs {
  position: absolute;
  top: 100%;
  width: 27px;
  height: 27px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  cursor: pointer;
  border: 4px solid #ff821e;
  opacity: 0.5;
}
</style>

这一篇文章是自定义进度条,上一篇文章使用的是element ui 里的el-slider滑块,根据实际的需求来做不同处理就可以实现拖拽进度条的效果。

GitHub 加速计划 / vu / vue
207.55 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:3 个月前 )
73486cb5 * chore: fix link broken Signed-off-by: snoppy <michaleli@foxmail.com> * Update packages/template-compiler/README.md [skip ci] --------- Signed-off-by: snoppy <michaleli@foxmail.com> Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 5 个月前
e428d891 Updated Browser Compatibility reference. The previous currently returns HTTP 404. 5 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐