vue2.0实现音乐/视频播放进度条组件

关于“vue2.0实现音乐/视频播放进度条组件”的攻略,我们需要考虑到以下几个方面:

  1. 组件设计
  2. 组件实现
  3. 组件使用

组件设计

在设计组件时,我们需要考虑以下几个方面:

  1. 组件的功能需求:播放进度条组件需要提供能够显示当前播放进度和总时长的功能,以及能够拖动改变播放进度的功能。
  2. 状态管理:我们需要维护当前播放时间、总时长和拖动状态的状态。
  3. 组件结构:播放进度条组件可以横向或竖向显示,我们可以考虑使用flex布局或absolute定位实现。

组件实现

在组件实现时,我们需要完成以下几个步骤:

  1. 组件结构设计:在template模板中使用 div、span、input等基本html元素构建组件结构。
  2. 数据管理:使用 props将播放的总时长和当前播放时间传入组件,通过data来定义组件需要维护的内部状态,包括播放开始时间、拖动状态和当前进度等值。
  3. 事件处理:使用 @mousedown、@mousemove、@mouseup和 @click 等事件处理函数,完成播放进度条拖动、重新开始播放等功能。
  4. 时长转换:处理组件接收到的时间单位,可以通过 Math.floor、PadStart 等API处理显示效果。

下面是一个基础示例:

<template>
  <div class="play-progress-bar">
    <span class="current-time">{{ currentTime }}</span>
    <input
      class="progress-bar"
      type="range"
      min="0"
      max="100"
      @mousedown="startDrag"
      @mousemove="dragging"
      @mouseup="stopDrag"
      @click="seekTo"
      :value="progress"
    />
    <span class="total-time">{{ totalTime }}</span>
  </div>
</template>

<script>
export default {
  name: "play-progress",
  props: {
    currentTime: Number, //当前播放时间
    totalTime: Number //总时长
  },
  data() {
    return {
      duration: 0, //播放开始时间
      dragging: false, //是否正在拖动
      progress: null //当前进度
    };
  },
  methods: {
    startDrag() {
      this.dragging = true;
      this.duration = this.currentTime;
    },
    dragging(evt) {
      if (!this.dragging) return;
      const target = evt.target;
      const rect = target.getBoundingClientRect();
      const offsetX = evt.clientX - rect.left;
      const progress = offsetX / target.offsetWidth;
      this.progress = progress;
    },
    stopDrag(evt) {
      if (!this.dragging) return;
      this.dragging = false;
      const target = evt.target;
      const rect = target.getBoundingClientRect();
      const offsetX = evt.clientX - rect.left;
      const progress = offsetX / target.offsetWidth;
      this.progress = progress;
      this.seekTo();
    },
    seekTo() {
      const time = this.progress * this.totalTime;
      this.$emit("change", time);
      this.duration = time;
    }
  },
  computed: {
    progress: {
      set(val) {
        if (!this.dragging) return;
        this.$emit("change", val * this.totalTime);
        this.duration = val * this.totalTime;
      },
      get() {
        return this.totalTime && this.currentTime
          ? (this.currentTime / this.totalTime) * 100
          : 0;
      }
    }
  }
};
</script>

<style scoped>
.play-progress-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  height: 30px;
  background-color: #aaa;
  position: relative;
}
.progress-bar {
  width: 100%;
  height: 4px;
  -webkit-appearance: none;
  background-color: #333;
  outline: none;
  cursor: pointer;
  position: relative;
  z-index: 1;
}
.progress-bar::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: #333;
  position: relative;
  z-index: 2;
}
.current-time,
.total-time {
  margin-left: 10px;
  margin-right: 10px;
  font-size: 12px;
  color: #333;
}
</style>

除此之外,我们还可以根据具体需求进行进一步的组件优化和功能拓展,例如对进度条进行美化、添加缓存等功能。

下面是一个进阶示例:

<template>
  <div class="play-progress-bar">
    <div class="progress-bar-wrap">
      <div class="progress-buffer-bar" :style="{ width: bufferedProgress + '%' }"></div>
      <div class="progress-point" :style="{ left: progress + '%' }">
        <span class="current-time">{{ currentTime | formatTime }}</span>
        <span class="point" @click="seekTo"></span>
      </div>
      <div class="progress-play-bar" :style="{ width: progress + '%' }"></div>
    </div>
    <span class="total-time">{{ totalTime | formatTime }}</span>
  </div>
</template>

<script>
export default {
  name: "play-progress",
  props: {
    currentTime: Number,
    totalTime: Number,
    bufferProgress: Number
  },
  filters: {
    formatTime(value) {
      if (!value) return "00:00";

      let minute = Math.floor(value / 60);
      let second = Math.floor(value % 60);

      minute = minute < 10 ? "0" + minute : minute;
      second = second < 10 ? "0" + second : second;

      return `${minute}:${second}`;
    }
  },
  computed: {
    progress() {
      if (this.totalTime === 0) {
        return 0;
      } else {
        return (this.currentTime / this.totalTime) * 100;
      }
    },
    bufferedProgress() {
      if (this.totalTime === 0) {
        return 0;
      } else {
        return (this.bufferProgress / this.totalTime) * 100;
      }
    }
  },
  methods: {
    seekTo(evt) {
      evt.stopPropagation();
      const target = evt.target;
      const rect = target.getBoundingClientRect();
      const offsetX = evt.clientX - rect.left;
      const progress = offsetX / target.offsetWidth;
      this.$emit("seekto", progress);
    }
  }
};
</script>

<style scoped>
.play-progress-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  height: 30px;
  background-color: #aaa;
  padding: 0 10px;
  position: relative;
}
.progress-bar-wrap {
  width: 100%;
  height: 4px;
  background-color: #ddd;
  cursor: pointer;
  position: relative;
}
.progress-buffer-bar {
  background-color: #666;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
}
.progress-play-bar {
  background-color: #333;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
}
.progress-point {
  position: absolute;
  top: -14px;
  left: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
}
.progress-point .current-time {
  display: inline-block;
  height: 16px;
  line-height: 16px;
  font-size: 12px;
  padding: 0 6px;
  margin-right: 8px;
  border-radius: 2px;
  background-color: #666;
  color: #fff;
}
.progress-point .point {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: #333;
  cursor: pointer;
}
.total-time {
  font-size: 12px;
  color: #333;
}
</style>

在这个示例中,我们添加了缓冲进度条,支持点击缓冲区间快速跳转到指定播放位置,并添加了时间格式化Filter等功能。

组件使用

在实际使用我们的播放进度条组件时,我们只需要将组件引用在需要播放的组件中,并传递相应的参数即可。例如:

<template>
  <section>
    <h2>MUSIC</h2>
    <audio src="./music.mp3" ref="audio" @timeupdate="updateTime" @progress="updateBuffer"></audio>
    <play-progress
      :current-time="currentTime"
      :total-time="totalTime"
      :buffer-progress="bufferProgress"
      @seekto="handleSeekTo"
    />
  </section>
</template>

<script>
import PlayProgress from "./PlayProgress";

export default {
  name: "Music",
  components: {
    PlayProgress
  },
  data() {
    return {
      currentTime: 0,
      totalTime: 0,
      bufferProgress: 0
    };
  },
  methods: {
    updateTime(evt) {
      this.currentTime = evt.target.currentTime;
      this.totalTime = evt.target.duration;
    },
    updateBuffer(evt) {
      if (evt.target.buffered.length) {
        this.bufferProgress = evt.target.buffered.end(0);
      }
    },
    handleSeekTo(progress) {
      const time = progress * this.totalTime;
      this.$refs.audio.currentTime = time;
    }
  }
};
</script>

<style>
h2 {
  font-size: 24px;
  font-weight: bold;
  margin-bottom: 10px;
}
</style>

在这个示例中,我们在一个Music组件中引用了播放进度条组件,使用Audio元素播放音频,并通过$refs获取Audio组件实例,获取当前播放进度和总时长、缓冲进度并传递给播放进度条组件。当播放进度条组件发生变化时,我们通过@seekto事件处理函数和$refs获取的Audio组件实例来更新播放进度和总时长。

以上便是solidot教程中“vue2.0实现音乐/视频播放进度条组件”的完整攻略。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue2.0实现音乐/视频播放进度条组件 - Python技术站

(0)
上一篇 2023年5月29日
下一篇 2023年5月29日

相关文章

  • Ant Design封装年份选择组件的方法

    Ant Design是一个流行的UI组件库,它提供了多个常用的组件,但是在特定的业务场景下,我们可能需要定制一些自己的组件,如年份选择组件。在本文中,我们将探讨如何使用Ant Design封装年份选择组件。 第一步:安装Ant Design npm install antd 安装完成后,我们需要在项目中引入Ant Design: import { DateP…

    Vue 2023年5月29日
    00
  • vue.js给动态绑定的radio列表做批量编辑的方法

    针对这个问题,我将为您提供关于Vue.js实现动态绑定radio列表批量编辑的完整攻略,以下是具体步骤: 步骤一:定义数据 首先需要定义一个数组来存储动态生成的radio列表,例如: data() { return { options: [ {id: 1, value: ‘option1’, checked: false}, {id: 2, value: ‘…

    Vue 2023年5月29日
    00
  • Vue3源码分析侦听器watch的实现原理

    下面是关于“Vue3源码分析侦听器watch的实现原理”的完整攻略。 理论基础 在学习 Vue3 的侦听器 watch 实现原理之前,我们需要先了解一下 Vue2 中的侦听器实现原理。在 Vue2 中,我们使用 Object.defineProperty 方法为组件实例对象上的数据属性设置 get 和 set 方法,从而实现了对某个数据属性的侦听。但是这种方…

    Vue 2023年5月29日
    00
  • vsCode中vue文件无法提示html标签的操作方法

    针对vsCode中vue文件无法提示html标签的情况,可以按照以下步骤进行操作: 安装Vetur插件 Vetur是一款vsCode的插件,主要提供语法高亮、格式化、代码片段和错误提示等功能,适用于Vue.js开发。因此,在使用vsCode编辑Vue文件时,我们需要安装并启用Vetur插件,这样就能够解决无法提示html标签的问题。 具体操作如下: 在vsC…

    Vue 2023年5月28日
    00
  • Bootstrap3 datetimepicker控件使用实例

    Bootstrap3 datetimepicker控件使用实例 介绍 datetimepicker控件是基于Bootstrap3的开源jQuery插件,用于日期和时间选择。它具有用户友好的界面,易于使用和高度可定制的特点。本文将详细介绍datetimepicker控件的使用方法和示例。 安装 要使用datetimepicker控件,首先需要引入相关的库文件:…

    Vue 2023年5月28日
    00
  • vue强制刷新组件的方法示例

    下面是对于 “vue强制刷新组件的方法示例” 的详细讲解攻略: Vue 强制刷新组件方法 在 Vue 中,当我们需要对组件进行强制刷新时,可以使用以下两种方式: 使用 key 属性 Vue 中,每个组件都可以设置一个 key 属性,当组件的 key 值改变时,组件会被强制重新渲染。 例如, <template> <div> <b…

    Vue 2023年5月29日
    00
  • vue中动态添加style样式的几种写法总结

    当我们在Vue中需要动态添加样式时,我们可以使用以下几种方法: 使用class绑定 Vue中可以使用:class或者:v-bind指令将一个变量与class属性绑定起来,这样我们可以通过改变变量的值来改变元素的class属性,从而改变样式。 <template> <div :class="{ ‘selected’: isSelec…

    Vue 2023年5月27日
    00
  • 基于vue v-for 多层循环嵌套获取行数的方法

    要在Vue的模板中多层循环嵌套并获取每层循环的行数,可以使用如下的方法: <template> <div> <div v-for="(group, index) in groups" :key="index"> <div v-for="(item, i) in gro…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部