vue3.0的练习——fileView组件——文件预览组件封装
vue3.0的练习——fileView组件——文件预览组件封装
·
vue3.0的练习——fileView组件——文件预览组件封装
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>
更多推荐
所有评论(0)