video-player组件的使用-参考下面的链接

vue-video-player——vue播放器插件的使用——基础积累:http://t.csdn.cn/CZciG

FileView组件——文件预览组件自行封装

html代码
<template>
	<div id="FileView" @contextmenu.prevent="preventHandle">
		<template v-if="fileType=='video'">
			<video-player id="video-player" class="video-player vjs-custom-skin" ref="videoPlayer" :playsinline="true" :options="playerOptions"></video-player>
		</template>
		<template v-if="fileType=='pdf'">
			<PDFView :fileUrl="fileUrl" @fullHandle="PDFFull"></PDFView>
		</template>
		<template v-if="fileType==""image">
			<img :src="fileUrl" alt class="fileImg" />
		</template>
	</div>
</template>
js代码
import {ref,defineComponent,getCurrentInstace} from 'vue';
import PDFView from './PDfView.vue';
export default defineComponent({
components:{
	PDFView
},
props:{
	fileType:{
		type:String,
		default:'video',
	},
	fileUrl:String,
	videoPlay:{
		type:Boolean,
		default:true,
	}
},
setup(props){
	const videoPlayer = ref();
	const {proxy} = getCurrentInstace();
	let fileUrl = ref('');
	return {
		preventHandle:()=>{
			return false;
		},
		videoPlayer,
		playerOptions:{
			//播放速度
			playbackRates:[],
			//如果true,浏览器准备好时开始回放
			autoplay:props.videoPlay,
			//默认情况下将会消除任何音频
			muted:false,
			//导致视频一结束就重新开始
			loop:true,
			//建议浏览器在<video>加载元素后是否应该开始下载视频数据,auto浏览器选择最佳行为,立即开始加载视频
			preload:'auto',
			language:'zh-CN',
			//将播放器置于流畅模式,并在计算播放器的动态大小时使用该值,值应该代表一个比例,用冒号分割的两个数字,
			aspectRation:'16:9',
			//当true时,video.js player将拥有流体大小。换句话说,它将按照比例缩放以适应其容器。
			fluid:true,
			sources:[
				{
					//类型
					type:'video/mp4',
					//url地址
					src:props.fileUrl
				}
			],
			//你的封面地址
			poster:'',
			//允许覆盖video.js无法播放媒体源时显示默认的信息
			notSupportedMessage:'此视频暂无法播放,请稍后再试',
			flash:{hls:{withCredentials:false}},
			html5:{hls:{withCredentials:false}},
			controlBar:{
				timeDivider:true,
				durationDisplay:true,
				remainingTimeDisplay:false,
				//全屏按钮
				fullscreenToggle:true,
			}
		}
	}
}
})
css代码
<style lang="less">
#FileView{
	height:100%;
	.fileImg{
		height:100%;
		width:auto;
		margin:0 auto;
	}
	.video-player{
		height:50vh;
		width:100%;
		background:#000;
		.video-js.vjs-fluid{
			height:100%;
			padding:0 !important;
		}
		.vjs-progress-control{
			pointer-events:none;
		}
		.vjs-big-play-button{
			border:none;
			background:transparent !important;
			&:active{
				background:transparent;
			}
			.vjs-icon-placeholder{
				font-size:1rem;
			}
		}
	}
}
</style>

PDFView组件——子组件

html代码
<template>
	<div id="pdf-container" @scroll="pageScroll">
		<canvas v-for="pageIndex in pdfPages" :id="'pdf-canvas-'+pageIndex" :key="pageIndex"></canvas>
		<div class="btnBox">
			<CaretLeftOutlined v-if="currentPage !== 1" @click="jumpPage('prev')" style="cursor:pointer" />
			<p class="pageNum">{{currentPage}}/{{pdfPages}}</p>
			<CaretRightOutlined v-if="currentPage!==pdfPages" @click="jumpPage('next')" style="cursor:pointer"/>
			<p class="fullScreen" @click="fullScreen">
				<FullscreenOutlined />
				<span class="txt">全屏</span>
			</p>
		</div>
		<div class="scaleBox">
			<MinusCircleOutlined v-if="pdfScale>0.9" @click="changeSize('minus')"/>
			<span class="scaleNum">{{((pdfScale*100).toFixed(0))+'%'}}</span>
			<PlusCircleOutlined v-if="pdfScale<1.9" @click="changeSize('plus')"/>
		</div>
	</div>
</template>
js代码
<script>
import {
  defineComponent,
  onMounted,
  nextTick,
  ref,
  getCurrentInstance
} from "vue";
import {
  CaretLeftOutlined,
  CaretRightOutlined,
  FullscreenOutlined,
  PlusCircleOutlined,
  MinusCircleOutlined
} from "@ant-design/icons-vue";
import * as PdfJs from "pdfjs-dist/legacy/build/pdf.js";
import { message } from "ant-design-vue";
export default defineComponent({
  components: {
    CaretLeftOutlined,
    CaretRightOutlined,
    FullscreenOutlined,
    PlusCircleOutlined,
    MinusCircleOutlined
  },
  props: {
    fileUrl: String
  },
  setup(props) {
    const { proxy } = getCurrentInstance();
    let pdfDoc = "",
      pdfPages = ref(0),
      currentPage = ref(1),
      pdfScale = ref(1),
      isFull = ref(false);

    const loadFile = url => {
      proxy
        .axios("GET", "/api/app/file/file-to-stream", {
          params: { fileUrl: props.fileUrl }
        })
        .then(res => {
          // console.log(props.fileUrl)
          let blob = dataURLtoBlob(res.Data);
          PdfJs.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/build/pdf.worker.entry");
          const loadingTask = PdfJs.getDocument(URL.createObjectURL(blob));
          loadingTask.promise
            .then(pdf => {
              // console.log(pdf)
              pdfDoc = pdf;
              pdfPages.value = pdfDoc.numPages;
              nextTick(() => {
                renderPage(currentPage.value); // 表示渲染第 1 页
              });
            })
            .catch(() => {
              message.warning("文件解析错误");
            });
        });
    };
    const dataURLtoBlob = dataurl => {
      let bstr = atob(dataurl);
      let n = bstr.length;
      let u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new Blob([u8arr], { type: "application/pdf" });
    };
    const renderPage = num => {
      pdfDoc.getPage(num).then(page => {
        currentPage.value = num;
        const canvas = document.getElementById("pdf-canvas-" + num);
        const ctx = canvas.getContext("2d");
        const dpr = window.devicePixelRatio || 1;
        const bsr =
          ctx.webkitBackingStorePixelRatio ||
          ctx.mozBackingStorePixelRatio ||
          ctx.msBackingStorePixelRatio ||
          ctx.oBackingStorePixelRatio ||
          ctx.backingStorePixelRatio ||
          1;
        const ratio = dpr / bsr;
        const viewport = page.getViewport({ scale: pdfScale.value });
        canvas.width = viewport.width * ratio;
        canvas.height = viewport.height * ratio;
        canvas.style.width = viewport.width + "px";
        canvas.style.height = viewport.height + "px";
        ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
        const renderContext = {
          canvasContext: ctx,
          viewport: viewport
        };
        page.render(renderContext);
      });
    };
    const pageScroll = e => {
      const scrollTop = e.target.scrollTop;
      const clientHeight = e.target.clientHeight;
      const scrollHeight = e.target.scrollHeight;
      // if (scrollTop + clientHeight+200 >= scrollHeight) {
        if (currentPage.value < pdfPages.value) {
          let current = currentPage.value;
          current = current + 1;
          nextTick(() => {
            renderPage(current);
          });
          // e.target.scrollTop = 0;
        }
      // }
    };
    //前一页,上一页
    const jumpPage = type => {
      if (type == "prev") {
        if (currentPage.value > 1) currentPage.value--;
      } else {
        if (currentPage.value < pdfPages.value) currentPage.value++;
      }
      renderPage(currentPage.value);
    };
    //全屏
    const fullScreen = () => {
      if (isFull.value) {
        exitFullscreen();
        return false;
      }
      isFull.value = true;
      let doc = document.documentElement;
      if (doc.requestFullscreen) {
        doc.requestFullscreen();
      } else if (doc.mozRequestFullScreen) {
        doc.mozRequestFullScreen();
      } else if (doc.webkitRequestFullscreen) {
        doc.webkitRequestFullscreen();
      } else if (doc.msRequestFullscreen) {
        doc.msRequestFullscreen();
      }
      renderPage(currentPage.value);
    };
    //退出全屏
    const exitFullscreen = () => {
      isFull.value = false;
      if (document.exitFullscreen) {
        document.exitFullscreen();
      } else if (document.mozExitFullScreen) {
        document.mozExitFullScreen();
      } else if (document.webkitExitFullscreen) {
        document.webkitExitFullscreen();
      }
      renderPage(currentPage.value);
    };
    //放大和缩小
    const changeSize = type => {
      if (type == "minus") {
        pdfScale.value = pdfScale.value - 0.1;
      } else {
        pdfScale.value = pdfScale.value + 0.1;
      }
     renderPage(currentPage.value);
    };
    onMounted(() => {
      loadFile();
    });
    return {
      pdfDoc,
      pdfPages,
      pdfScale,
      currentPage,
      jumpPage,
      fullScreen,
      changeSize,
      pageScroll
    };
  }
});
</script>
css代码
<style lang="less">
#pdf-container {
  height: 80vh;
  overflow-y: auto;
  text-align: center;
  background-color: #f5f5f5;
  display: flex;
  flex-direction: column;
  align-items: center;
  .btnBox {
    width: 5.12rem;
    height: 1.18rem;
    background: rgba(0, 0, 0, 0.5);
    border-radius: 0.12rem;
    position: absolute;
    bottom: 0.79rem;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;

    p {
      font-size: 0.28rem;
      &.pageNum {
        margin: 0 0.04rem;
      }
      &.fullScreen {
        cursor: pointer;
        padding-left: 0.28rem;
        border-left: 1px dotted #fff;
        margin-left: 0.4rem;
        .txt {
          padding-left: 0.2rem;
        }
      }
    }
  }
  .scaleBox {
    position: absolute;
    bottom: 1rem;
    right: 2rem;
    .scaleNum{
      padding:0.14rem;
      width:1.2rem;
      min-width:60PX;
    }
  }
}
</style>
Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐