您现在的位置是:首页 >技术交流 >vue项目-视频预览组件网站首页技术交流

vue项目-视频预览组件

辣椒大山岭二号 2025-07-20 12:01:03
简介vue项目-视频预览组件

一、功能

  1. 组件接收一个url,为视频链接;
  2. 组件为全屏预览组件,背景色为透明灰色
  3. 视频宽高自适应,需要保证最长边完全显示
  4. 允许点击透明灰色部分预览组件消失
  5. 视频播放的一些功能需要有,例如播放、暂停、进度条、调节音量等等

二、视频预览效果

在这里插入图片描述

三、使用方法

<template>
  <div>
    <!-- 触发按钮 -->
    <button @click="showVideo = true">预览视频</button>
    <!-- 视频预览组件 -->
    <VideoPreview
      v-model:visible="showVideo"
      :url="videoUrl"
    />
  </div>
</template>
<script setup>
import { ref } from 'vue'
import VideoPreview from '@/components/videoPreview/index.vue'
const showVideo = ref(false)
const videoUrl = ref('视频URL')
</script>

四、视频预览组件代码

<!-- 视频预览 -->
<template>
  <div 
    v-if="visible" 
    class="video-preview-container"
    @click.self="handleClose"
  >
    <div class="video-wrapper">
      <!-- 视频加载时显示加载状态 -->
      <div v-if="loading" class="loading-wrapper">
        <span class="loading-text">视频加载中...</span>
      </div>
      <video
        ref="videoRef"
        :src="url"
        controls
        class="video-player"
        @click.stop
        @loadstart="handleLoadStart"
        @canplay="handleCanPlay"
        @error="handleError"
        muted
      >
        你的浏览器不支持 video 标签。
      </video>
      <!-- 显示错误信息 -->
      <div v-if="errorMsg" class="error-message">
        {{ errorMsg }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'VideoPreview',
  props: {
    // 视频URL地址
    url: {
      type: String,
      required: true
    },
    // 控制预览组件的显示和隐藏
    visible: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      loading: false, // 视频加载状态
      errorMsg: '' // 错误信息
    }
  },
  watch: {
    // 监听visible变化
    visible(newVal) {
      if (!newVal && this.$refs.videoRef) {
        // 关闭时暂停视频
        this.$refs.videoRef.pause()
      } else if (newVal && this.$refs.videoRef) {
        // 打开时自动播放并取消静音
        this.$refs.videoRef.play().then(() => {
          this.$refs.videoRef.muted = false
        }).catch(err => {
          console.warn('自动播放失败:', err)
        })
      }
    },
    // 当URL改变时,重置错误状态
    url() {
      this.errorMsg = ''
    }
  },
  methods: {
    // 关闭预览
    handleClose() {
      this.$emit('update:visible', false)
    },
    // 视频开始加载
    handleLoadStart() {
      this.loading = true
      this.errorMsg = ''
    },
    // 视频可以播放时
    handleCanPlay() {
      this.loading = false
      // 首次加载完成时自动播放并取消静音
      if (this.visible) {
        this.$refs.videoRef.play().then(() => {
          this.$refs.videoRef.muted = false
        }).catch(err => {
          console.warn('自动播放失败:', err)
        })
      }
    },
    // 视频加载错误处理
    handleError() {
      this.loading = false
      this.errorMsg = '视频加载失败,请检查链接是否正确'
    }
  }
}
</script>

<style scoped>
.video-preview-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 9999;
}

.video-wrapper {
  position: relative;
  max-width: 90vw;
  max-height: 90vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.video-player {
  max-width: 100%;
  max-height: 90vh;
  object-fit: contain;
  background-color: #000; /* 视频加载时的背景色 */
}

/* 加载状态样式 */
.loading-wrapper {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 1;
}

.loading-text {
  color: #fff;
  font-size: 14px;
  background-color: rgba(0, 0, 0, 0.7);
  padding: 8px 16px;
  border-radius: 4px;
}

/* 错误信息样式 */
.error-message {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: #ff4d4f;
  background-color: rgba(0, 0, 0, 0.7);
  padding: 8px 16px;
  border-radius: 4px;
  font-size: 14px;
}
</style> 
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。