vue2+vant+vue-pdf实现app预览pdf
1.安装vue-pdfnpm install --save vue-pdf2.使用1)不分页(新建pdfNoPage.vue),代码如下/** @Author: duyan* @Date: 2020-09-25 09:11:13* @Last Modified by: duyan* @Last Modified time: 2020-09-25 10:19:25*/<template>
·
1.安装vue-pdf
npm install --save vue-pdf
2.使用
1)不分页(新建pdfNoPage.vue),代码如下
/*
* @Author: duyan
* @Date: 2020-09-25 09:11:13
* @Last Modified by: duyan
* @Last Modified time: 2020-09-25 10:19:25
*/
<template>
<div class="pdfNoPage">
<div v-if="isLoading" class="mask">
<loading size="24px" vertical>加载中...</loading>
</div>
<div class="pdf-box">
<pdf
v-for="i in numPages"
:key="i"
:src="pdfSrc"
:page="i"
@page-loaded="pageLoaded"
/>
</div>
</div>
</template>
<script>
import pdf from 'vue-pdf'
import { Loading } from 'vant'
export default {
metaInfo: {
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=2,user-scalable=yes' }
]
},
// 名字
name: 'PdfNoPage',
// 部件
components: {
pdf,
Loading
},
// 静态
props: {
pdfSrc: {
type: String,
default: ''
}
},
// 数据
data() {
return {
numPages: undefined,
isLoading: true
}
},
// 属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用;
computed: {
},
// 对象内部的属性监听,也叫深度监听
watch: {
},
// 请求数据
created() {
},
mounted() {
this.getNumPages(this.pdfSrc)
},
// 方法表示一个具体的操作,主要书写业务逻辑;
methods: {
getNumPages(url) {
var loadingTask = pdf.createLoadingTask(url)
loadingTask.promise.then(pdf => {
this.url = loadingTask
this.numPages = pdf.numPages
}).catch((err) => {
console.log(err)
})
},
// 等pdf页数加载完成的时候,隐藏加载框
pageLoaded(num) {
if (num === this.numPages) {
this.isLoading = false
}
}
}
}
</script>
<style scoped lang="scss">
// 加载框
.mask {
width: 100vw;
height: 100%;
position: relative;
.van-loading {
position: absolute;
left: 50%;
top:50%;
transform: translate(-50%,-50%);
}
}
.pdf-box {
padding: 10px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
max-width: 1024px;
width: 100%;
margin: 0 auto;
overflow-x: hidden;
height: 100% ;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
font-size: .28rem;
span {
width: 100%;
}
}
</style>
2).分页(新建pdfPage.vue),代码如下
/*
* @Author: duyan
* @Date: 2020-09-25 09:07:29
* @Last Modified by: duyan
* @Last Modified time: 2020-09-25 14:19:48
*/
<template>
<div class="pdfPage">
<div v-if="isLoading" class="mask">
<loading size="24px" vertical>加载中...</loading>
</div>
<!-- <v-touch style="height: calc(100% - 25px);" tag="div" @swipeleft="onSwipeLeft" @swiperight="onSwipeRight"> -->
<div
class="pdf-box"
@touchstart="touchstart"
@touchmove="touchmove"
@touchend="touchend"
>
<pdf
ref="pdf"
:src="pdfSrc"
:page="currentPage"
@num-pages="pageCount=$event"
@page-loaded="pageLoaded"
@loaded="loadPdfHandler"
/>
</div>
<!-- </v-touch> -->
<!--页码-->
<div v-show="fileType === 'pdf'" class="pdf">
<van-row type="flex" justify="space-between">
<van-col span="12" style="text-align:center">
<div class="touch">
<van-button
round
size="mini"
type="primary"
:class="{select:idx==0}"
@touchstart="idx=0"
@touchend="idx=-1"
@click="scaleD"
>
放大
</van-button>
<van-button
round
size="mini"
type="primary"
:disabled="scale===100?true:false"
:class="{select:idx==1}"
@touchstart="idx=1"
@touchend="idx=-1"
@click="scaleX"
>
缩小
</van-button>
</div>
</van-col>
<van-col span="12" style="text-align:center">
<div class="pagesize">
<!--上一页-->
<van-button
round
size="mini"
type="info"
class="turn"
:disabled="currentPage==1?true:false"
:class="{grey: currentPage==1}"
@click="changePdfPage(0)"
>上页</van-button>
{{ currentPage }} / {{ pageCount }}
<!--下一页-->
<van-button
round
size="mini"
type="info"
class="turn"
:disabled="currentPage==pageCount?true:false"
:class="{grey: currentPage==pageCount}"
@click="changePdfPage(1)"
>下页</van-button>
</div>
</van-col>
</van-row>
</div>
</div>
</template>
<script>
import pdf from 'vue-pdf' // 引入pdf组件
import { Loading } from 'vant'
export default {
metaInfo: {
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=2,user-scalable=yes' }
]
},
// 名字
name: 'PdfPage',
// 部件
components: {
pdf,
Loading
},
// 静态
props: {
pdfSrc: {
type: String,
default: ''
}
},
// 数据
data() {
return {
currentPage: 0, // pdf文件页码
pageCount: 0, // pdf文件总页数
fileType: 'pdf', // 文件类型
isLoading: true,
scale: 100, // 放大系数
idx: -1,
touchDistance: 0,
previousPinchScale: 1,
startTime: 0,
startX: null,
startY: null,
moveX: null,
moveY: null,
eLen: 0
}
},
// 属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用;
computed: {
},
// 对象内部的属性监听,也叫深度监听
watch: {
},
// 请求数据
created() {
},
mounted() {
this.loadPdfHandler()
// 有时PDF文件地址会出现跨域的情况,这里最好处理一下
this.pdfSrc = pdf.createLoadingTask(this.pdfSrc)
},
// 方法表示一个具体的操作,主要书写业务逻辑;
methods: {
// 改变PDF页码,val传过来区分上一页下一页的值,0上一页,1下一页
changePdfPage(val) {
console.log(val)
if (val === 0 && this.currentPage > 1) {
this.currentPage--
// console.log(this.currentPage)
}
if (val === 1 && this.currentPage < this.pageCount) {
this.currentPage++
// console.log(this.currentPage)
}
},
// 放大
scaleD() {
this.scale += 5
this.$refs.pdf.$el.style.width = parseInt(this.scale) + '%'
},
// 缩小
scaleX() {
if (this.scale === 100) {
return
}
this.scale += -5
this.$refs.pdf.$el.style.width = parseInt(this.scale) + '%'
},
// 等pdf页数加载完成的时候,隐藏加载框
pageLoaded(num) {
if (num === this.currentPage) {
this.isLoading = false
}
},
// pdf加载时
loadPdfHandler(e) {
this.currentPage = 1 // 加载的时候先加载第一页
},
_getDistance(xLen, yLen) {
return Math.sqrt(xLen * xLen + yLen * yLen)
},
touchstart(e) {
this.startTime = this._getTime()
this.startX = e.touches[0].pageX
this.startY = e.touches[0].pageY
if (e.touches.length > 1) {
const point1 = e.touches[0]
const point2 = e.touches[1]
const xLen = Math.abs(point2.pageX - point1.pageX)
const yLen = Math.abs(point2.pageY - point1.pageY)
this.touchDistance = this._getDistance(xLen, yLen)
}
},
touchmove(e) {
this.moveX = e.touches[0].pageX
this.moveY = e.touches[0].pageY
// e.touches.length为手指的个数
this.eLen = e.touches.length
if (e.touches.length > 1) {
const xLen = Math.abs(e.touches[0].pageX - e.touches[1].pageX)
const yLen = Math.abs(e.touches[0].pageY - e.touches[1].pageY)
const touchDistance = this._getDistance(xLen, yLen)
if (this.touchDistance) {
const pinchScale = touchDistance / this.touchDistance
this.previousPinchScale = pinchScale
}
}
},
_getTime() {
return new Date().getTime()
},
touchend(e) {
// const timestamp = this._getTime()
if (this.scale === 100 && this.eLen === 1) {
if (this.moveX !== null && this.moveX - this.startX > 30) {
if (this.currentPage !== 1) {
this.changePdfPage(0)
}
} else if (this.moveX !== null && this.moveX - this.startX < -30) {
if (this.currentPage < this.pageCount) {
this.changePdfPage(1)
}
}
}
// alert(this.eLen)
// if (this.moveX !== null && Math.abs(this.moveX - this.startX) > 5 ||
// this.moveY !== null && Math.abs(this.moveY - this.startY) > 5) {
// if (this.eLen >= 2) { // 手指移动的位移要大于10像素并且手指和屏幕的接触时间要短于500毫秒
// // alert('双指')
// alert(this.previousPinchScale)
// // this._renderPage(1, this.previousPinchScale)
// this.$refs.pdf.$el.style.width = parseInt(this.previousPinchScale * this.scale) + '%'
// this.scale = this.scale * this.previousPinchScale
// this.eLen = 0
// }
// }
},
onSwipeLeft() {
debugger
},
onSwipeRight() {
debugger
}
}
}
</script>
<style scoped lang="scss">
// 加载框
.mask {
width: 100vw;
height: 100%;
position: relative;
.van-loading {
position: absolute;
left: 50%;
top:50%;
transform: translate(-50%,-50%);
}
}
.pdfPage{
height: calc(100% - 25px);
}
.pdf-box {
padding: 10px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
max-width: 1024px;
width: 100%;
margin: 0 auto;
overflow-x: auto;
height: 100% ;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
font-size: .28rem;
span {
width: 100%;
}
}
.pagesize{
text-align: center;
}
</style>
2).引用
js
import pdfNoPage from '@/views/scan/pdfNoPage'
import pdfPage from '@/views/scan/pdfPage'
html:
<div style="height:calc(100% - 46px)">
<pdf-no-page :pdf-src="pdfSrc" />
</div>
<div style="height:calc(100% - 46px)">
<pdf-page v-if="flag" :pdf-src="pdfSrc" />
</div>
data:(文件路径,需要放在静态文件或者放在线上如oss等可以直接访问该路径)
pdfSrc: '',
坑:在做的时候还需要实现手指滚动翻页以及双指放大的功能,一开始用的是vue-toch,使用参考vue-toch但是引用了之后不起作用,后面直接用了js的手势事件来写,翻页和缩放也都实现了,但是在监听手指个数的时候会出问题(应该是几个手指一起的时候,每个手指开始和结束触碰的时间都不一样),所以最终缩放也就没做成。手势事件参考js手势事件
更多推荐
已为社区贡献3条内容
所有评论(0)