绿满眶商城微信小程序-uniapp
xiangpei
2025-06-09 cb07426138f701d38e11e9469d9ba4735098e7e0
自定义视频进度条
2个文件已修改
168 ■■■■■ 已修改文件
pages.json 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/tabbar/index/home.vue 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages.json
@@ -15,6 +15,7 @@
        }
    },
    "pages": [
        // 第一个就是首页
        {
            "path": "pages/tabbar/index/home",
@@ -22,6 +23,13 @@
                // "navigationBarTitleText" : "视频",
                "enablePullDownRefresh": false,
                "navigationStyle": "custom" // 隐藏顶部导航栏
            }
        },
        {
            "path" : "pages/tabbar/index/home1",
            "style" :
            {
                "navigationBarTitleText" : ""
            }
        },
        {
@@ -1395,7 +1403,7 @@
        "borderStyle": "black",
        "backgroundColor": "#ffffff",
        "list": [{
                "pagePath": "pages/tabbar/index/home",
                "pagePath": "pages/tabbar/index/home1",
                "iconPath": "static/tabbar/home.png",
                "selectedIconPath": "static/tabbar/home-s.png",
                "text": "首页"
pages/tabbar/index/home.vue
@@ -25,13 +25,39 @@
          :controls="false"
          :loop="true"
          :object-fit="item.objectFit"
          :enable-progress-gesture="false"
          class="video-item"
          @play="onPlay(item.id, index)"
          @pause="onPause(index)"
          @ended="onEnded(index)"
          @click="togglePlay(index)"
          @timeupdate="onTimeUpdate($event)"
          @loadedmetadata="onLoadedMetadata($event)"
        ></video>
        <!-- 自定义控制条 -->
        <view
            @touchstart="handleTouchStart"
            @touchmove="handleTouchMove"
            @touchend="handleTouchEnd"
            class="container">
          <!-- 进度条 - 整个区域可拖动 -->
          <view class="process-warp" :style="{ opacity: showProcess ? 1 : 0 }">
              <!-- 显示当前进度 -->
              <view class="progress-text">{{ hasPlayTime }}/{{formartDuration}}</view>
              <view
                class="progress-bar"
                id="progressBar"
              >
                <!-- 已填充部分 -->
                <view class="progress-fill" :style="{ width: progress + '%' }"></view>
              </view>
          </view>
        </view>
        
        <!-- 悬挂商品链接层 -->
        <view class="goods-link-warp">
@@ -181,8 +207,24 @@
import { getRecommendVideos, savePlayRecord, subscribe, getVideoComments, addVideoComment, thubmsUpComment, cancelThubmsUpComment } from "@/api/video.js";
import { changeCollect } from "@/api/collect.js";
export default {
  computed: {
        hasPlayTime() {
          return this.sliderFormatTime(this.progress > 0 ? this.duration * this.progress / 100 : 0);
        }
  },
  data() {
    return {
        currentTime: 0,
        formartDuration: '',
        duration: 0,
        startX: 0,
        progress: 0, // 视频进度
        startProgress : 0, // 开始滑动时的进度
        barLeft: 0, // 进度条左边界位置
        barWidth: 0, // 进度条宽度
        isDragging: false, // 是否正在拖动
        processHidenTimer: null, // 进度条隐藏定时器
        showProcess: false, // 是否显示进度条
        videoNoMore: false, // 是否还有更多视频
        commentNoMore: false, // 是否还有更多评论
        commentQuery: {
@@ -255,6 +297,16 @@
    this.initVideoContexts();
  },
  methods: {
      // 获取进度条的位置和尺寸
      getBarRect() {
        const query = uni.createSelectorQuery().in(this);
        query.select('#progressBar').boundingClientRect(rect => {
          if (rect) {
            this.barLeft = rect.left;
            this.barWidth = rect.width;
          }
        }).exec();
      },
        // 跳转个人主页
        jumpToHomePage(authorId) {
            uni.navigateTo({
@@ -351,6 +403,12 @@
            const input = this.$refs.commentInput;
            if (input) input.focus();
          });
        },
        // 进度条时间格式化 (00:00)
        sliderFormatTime(seconds) {
          const mins = Math.floor(seconds / 60);
          const secs = Math.floor(seconds % 60);
          return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
        },
        // 格式化时间
        formatTime(time) {
@@ -584,6 +642,8 @@
    },
    // 视频播放事件
    onPlay(id, index) {
        this.getBarRect()
        this.progress = 0
        console.log(id, index, "触发播放");
        if(index === this.currentIndex) {
            this.currentVideoIsPlaying = true;
@@ -613,7 +673,6 @@
        }
      this.startPauseTime = Date.now()
    },
    // 视频结束事件
    onEnded(index) {
      // this.currentVideoIsPlaying = false;
@@ -621,9 +680,66 @@
    
    // 记录播放时长
    onTimeUpdate(e) {
        this.playRecord.playAt = e.detail.currentTime
        this.playRecord.playAt = e.detail.currentTime;
        this.currentTime = e.detail.currentTime;
        this.progress = (e.detail.currentTime / this.duration) * 100
    },
    // 触摸开始
    handleTouchStart(e) {
      this.isDragging = true;
      this.showProcess = true;
      this.startProgress = this.progress; // 记录开始时的进度
      this.startX = e.touches[0].pageX;
      console.log("记录开始时的进度", this.startProgress);
      this.videoContexts[this.currentIndex].pause()
      // this.updateProgress(e);
    },
    
    // 触摸移动
    handleTouchMove(e) {
      if (!this.isDragging || !this.barWidth) return;
      clearTimeout(this.processHidenTimer)
      this.videoContexts[this.currentIndex].pause()
      this.updateProgress(e);
    },
    // 触摸结束
    handleTouchEnd() {
      this.isDragging = false;
      console.log("滑动结束", this.duration * this.progress);
      this.videoContexts[this.currentIndex].seek(this.duration * this.progress / 100)
      this.videoContexts[this.currentIndex].play()
      this.processHidenTimer = setTimeout(() => {
          this.showProcess = false;
        }, 1000);
    },
    // 更新进度
    updateProgress(e) {
        // 获取当前触摸点X坐标
        const currentX = e.touches[0].pageX;
        // 计算滑动距离(像素)
        const deltaX = currentX - this.startX;
        // 将像素距离转换为进度增量
        const deltaProgress = (deltaX / this.barWidth) * 100;
        console.log("进度增量", deltaProgress);
        // 计算新进度 = 开始时的进度 + 滑动增量
        let newProgress = this.startProgress + deltaProgress;
        // 限制范围在0-100之间
        newProgress = Math.max(0, Math.min(100, newProgress));
        this.progress = newProgress;
    },
    // 获取视频总时长
    onLoadedMetadata(e) {
      this.duration = e.detail.duration;
      this.formartDuration = this.sliderFormatTime(this.duration);
      console.log("视频总时长", this.duration);
    },
    // 保存播放记录
    async savePlayRecord() {
        console.log(Date.now(), this.playRecord.startPlayTime, this.totalHidenTime);
@@ -659,7 +775,7 @@
    
    .video-swiper {
      width: 100%;
      height: 100%;
      height: calc(100% - 50px);
    }
    
    .video-item {
@@ -1015,4 +1131,40 @@
    .thumbs-num {
        margin-left: 4rpx;
    }
    .container {
      display: flex;
      flex-direction: column;
      align-items: center;
      position: absolute;
      bottom: 0;
      width: 100%;
    }
    .progress-bar {
      position: relative;
      width: 100%;
      height: 16px;
      background-color: #eee;
      overflow: hidden;
    }
    .progress-fill {
      position: absolute;
      left: 0;
      top: 0;
      height: 100%;
      background-color: lightgray;
      transition: width 0.1s;
    }
    .process-warp {
        width: 100%;
        display: flex;
        flex-direction: column;
        align-items: center;
    }
    .progress-text {
      margin-top: 10px;
      font-size: 14px;
      color: #666;
    }
</style>