uniapp 如何自定义video进度条并实现缓冲功能

在uniapp中,如何自定义video组件的进度条样式并实现缓冲功能?官方文档提供的进度条样式比较局限,想要修改颜色、高度等外观,同时需要显示视频加载的缓冲进度。尝试过覆盖原生样式但效果不理想,是否有更完善的解决方案?最好能提供代码示例或实现思路。

2 回复

使用<video>组件的controls属性设为false,自定义进度条UI。通过@timeupdate监听播放进度,@progress获取缓冲进度。用<progress><view>绘制进度条,动态设置宽度。


在 UniApp 中自定义 video 组件的进度条并实现缓冲功能,可以通过以下步骤实现:

1. 使用 video 组件并绑定属性和事件

<template>
  <view>
    <video 
      :src="videoUrl" 
      :controls="false" 
      @timeupdate="onTimeUpdate"
      @loadedmetadata="onLoadedMetadata"
      @progress="onProgress"
      ref="videoRef"
    ></video>
    
    <!-- 自定义进度条 -->
    <view class="progress-container">
      <!-- 缓冲进度条 -->
      <view class="buffer-bar" :style="{ width: bufferPercent + '%' }"></view>
      <!-- 播放进度条 -->
      <view class="play-bar" :style="{ width: playPercent + '%' }"></view>
      <!-- 进度条滑块 -->
      <view 
        class="slider" 
        :style="{ left: playPercent + '%' }"
        @touchstart="onTouchStart"
        @touchmove="onTouchMove"
        @touchend="onTouchEnd"
      ></view>
    </view>
  </view>
</template>

2. JavaScript 逻辑实现

export default {
  data() {
    return {
      videoUrl: '你的视频地址',
      duration: 0,           // 视频总时长
      currentTime: 0,        // 当前播放时间
      buffered: 0,           // 缓冲长度
      playPercent: 0,        // 播放进度百分比
      bufferPercent: 0,      // 缓冲进度百分比
      isSeeking: false       // 是否正在拖动
    }
  },
  methods: {
    // 获取视频元数据
    onLoadedMetadata(e) {
      this.duration = e.detail.duration
    },
    
    // 播放时间更新
    onTimeUpdate(e) {
      if (!this.isSeeking) {
        this.currentTime = e.detail.currentTime
        this.playPercent = (this.currentTime / this.duration) * 100
      }
    },
    
    // 缓冲进度更新
    onProgress(e) {
      const video = this.$refs.videoRef
      if (video && this.duration > 0) {
        const buffered = video.buffered
        if (buffered.length > 0) {
          this.buffered = buffered.end(0)
          this.bufferPercent = (this.buffered / this.duration) * 100
        }
      }
    },
    
    // 触摸事件处理
    onTouchStart(e) {
      this.isSeeking = true
    },
    
    onTouchMove(e) {
      if (!this.isSeeking) return
      
      const touch = e.touches[0]
      const progressContainer = this.$el.querySelector('.progress-container')
      const rect = progressContainer.getBoundingClientRect()
      const percent = Math.max(0, Math.min(1, (touch.clientX - rect.left) / rect.width))
      
      this.playPercent = percent * 100
      this.currentTime = this.duration * percent
    },
    
    onTouchEnd() {
      this.isSeeking = false
      const video = this.$refs.videoRef
      if (video) {
        video.seek(this.currentTime)
      }
    }
  }
}

3. CSS 样式

.progress-container {
  position: relative;
  height: 4px;
  background: #ddd;
  margin: 10px 0;
}

.buffer-bar {
  position: absolute;
  height: 100%;
  background: #666;
  transition: width 0.3s;
}

.play-bar {
  position: absolute;
  height: 100%;
  background: #007AFF;
  z-index: 2;
}

.slider {
  position: absolute;
  width: 20px;
  height: 20px;
  background: #007AFF;
  border-radius: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
}

实现要点:

  • 使用 @progress 事件监听缓冲进度
  • 通过 buffered 属性获取已缓冲的时间段
  • 触摸事件处理进度条拖动
  • 使用 seek() 方法跳转到指定时间

这样即可实现自定义进度条,并显示缓冲效果。注意在真机测试时确保视频源支持缓冲检测。

回到顶部