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日

相关文章

  • Vue-cli Eslint在vscode里代码自动格式化的方法

    第一步:安装必要的工具和插件 首先,我们需要安装Vue-cli和Vscode这两个软件,Vue-cli用于创建Vue项目,Vscode用于编写和调试代码。同时,我们还需要安装Vscode的插件“ESLint”和“Prettier – Code formatter”,用于代码格式化和检测。 安装Vue-cli命令行工具,在终端中输入以下命令: npm inst…

    Vue 2023年5月28日
    00
  • Vue不能检测到数据变化的几种情况说明

    Vue是一款前端框架,其特点之一就是数据驱动视图,即根据数据的变化自动更新视图。但是,在某些情况下,Vue不能检测到数据的变化,导致视图没有更新。那么Vue不能检测到数据变化的几种情况有哪些呢?本攻略将一一讲解。 直接修改数组下标无法触发更新 Vue能够监听到数组的变化,但不能监听到数组下标的变化。如果直接修改数组下标,Vue将无法检测到数据的变化,也就无法…

    Vue 2023年5月28日
    00
  • 公共Hooks封装文件下载useDownloadFile实例详解

    我会为你详细讲解“公共Hooks封装文件下载useDownloadFile实例详解”的完整攻略。 什么是公共Hooks 公共Hooks是指在React项目中,可以被多个组件共享的可重用代码片段。它们通常被封装在统一的模块中,以便于其他组件引用和使用。 useDownloadFile Hook useDownloadFile Hook是一个公共Hooks封装文…

    Vue 2023年5月28日
    00
  • Vue this.$router.push(参数)实现页面跳转操作

    当我们使用Vue.js构建单页面应用时,有时需要在不同的页面之间进行路由跳转。Vue Router提供了一些方法来实现这一功能,其中之一是$this.$router.push()方法。以下是关于如何使用$this.$router.push()方法实现页面跳转操作的完整攻略。 前置准备 要使用Vue Router,需先安装Vue Router模块并配置路由。 …

    Vue 2023年5月27日
    00
  • Vue XStream 2016 中文破解版安装教程(附破解文件)

    下面我将为您详细讲解“Vue XStream 2016 中文破解版安装教程(附破解文件)”的完整攻略。具体步骤如下: 第一步:下载安装包和破解文件 首先,你需要下载 Vue XStream 2016 中文破解版的安装包和破解文件。可以在百度网盘或者其它资源网站中寻找下载链接。 下载好后,将其解压缩。 第二步:进入安装程序 进入解压缩后的文件夹,找到其中的“s…

    Vue 2023年5月27日
    00
  • vue实现前端保持筛选条件到url并进行同步参数设计

    Vue实现前端保持筛选条件到URL并进行同步参数设计的攻略主要分为以下几个步骤: 第一步:获取参数并解析 我们可以使用vue-router的query属性获取URL参数,然后解析成对象,方便我们进行筛选条件的操作。例如: // 获取URL参数 const query = this.$route.query // 解析参数成Object const filte…

    Vue 2023年5月27日
    00
  • Vue3 Axios拦截器封装成request文件的示例详解

    Vue3 Axios拦截器封装成request文件的示例详解 在Vue3项目中,我们通常会使用Axios来请求数据。为了增强代码的可维护性和重用性,我们可以将Axios的拦截器封装成一个request文件,方便统一管理和调用。下面是示例代码: request.js import axios from ‘axios’; import { getToken } …

    Vue 2023年5月28日
    00
  • Vue3实现全局loading指令的示例详解

    下面是关于“Vue3实现全局loading指令的示例详解”的完整攻略。 简介 在Vue3中,可以使用自定义指令来给DOM元素绑定一些额外的行为,比如全局loading指令。 实现步骤 第一步:创建指令 在Vue3中,我们可以使用app.directive()方法来创建一个指令。下面是一个简单的指令示例,实现了在元素上添加一个loading图标的功能: imp…

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