现在开始想写点东西来记录一下开发过程中爬的坑,一方面方便自己查看,也希望能帮到同样遇到此类问题的开发者。
 

pdfjs的setDocument 方式渲染页面快,适合大文件, 不需要自己渲染字体,那么如何在移动端实现手势动态缩放文档呢?下面贴出自己在vue项目中写的组件。

// src/components/pdf/pdf.js
<template>
<div class="pdf-view">
  <div id="viewerContainer" ref="container">
    <div id="viewer" class="pdfViewer" 
      @touchstart="touchstart" 
			@touchmove="touchmove" 
			@touchend="touchend"/>
  </div>
</div>
</template>
<script>
import getPdfjsDist from '@/components/pdf/getPdfjsDist'
export default {
  name: 'Pdf',
  props: {
    url: {
      type: String,
      default: ''
    },
    type: {
      type: String,
      default: 'svg'
    },
    pdfjsDistPath: {
      type: String,
      default: '../../../static'
    },
    DEFAULT_SCALE_DELTA:{
      type:Number,
      default:1.1
    },
    DEFAULT_SCALE_VALUE:{
      type:String,
      default:'auto'
    },
    MIN_SCALE:{
      type:Number,
      default:0.1
    },
    MAX_SCALE:{
      type:Number,
      default:10
    }
  },
  data() {
    return {
      pdfViewer: null,
      pdfLinkService: null,
      currentScale: 'page-width',
      loadingTask: null,
      touchDistance:0,
      previousPinchScale: 1,
      startTime: 0,
      startX:null,
      startY:null,
      moveX:null,
      moveY:null,
      eLen:0,
    }
  },

  methods: {
    onPagesInit({source}) {
      source.currentScaleValue = this.currentScale
    },
    async pdfLibInit() {
      let pdfjsLib = window.pdfjsLib;
      let pdfjsViewer = window.pdfjsViewer
      if (!pdfjsLib || !pdfjsViewer) {
        try {
          await getPdfjsDist(this.pdfjsDistPath)
          this.CMAP_URL = `${this.pdfjsDistPath}/pdfjs-dist/cmaps/`
          pdfjsLib = window.pdfjsLib;
          pdfjsLib.GlobalWorkerOptions.workerSrc = `${this.pdfjsDistPath}/pdfjs-dist/es5/build/pdf.worker.js`
          pdfjsViewer = window.pdfjsViewer
        } catch (error) {
          // console.log(error)
          // pdfjs文件获取失败
          return 
        }
      }

      const container = this.$refs.container
      const eventBus = new pdfjsViewer.EventBus();

      // (Optionally) enable hyperlinks within PDF files.
      const pdfLinkService = new pdfjsViewer.PDFLinkService({
        eventBus: eventBus,
      });
      this.pdfLinkService = pdfLinkService
      const pdfViewer = new pdfjsViewer.PDFViewer({
        container: container,
        eventBus: eventBus,
        linkService: pdfLinkService,
        renderer: this.type,
        textLayerMode: 0,
        downloadManager: new pdfjsViewer.DownloadManager({}),
        enableWebGL: true
      });
      this.pdfViewer = pdfViewer
      pdfLinkService.setViewer(pdfViewer);

      eventBus.on("pagesinit", this.onPagesInit);
    },
    _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) {
        let point1 = e.touches[0];
        let point2 = e.touches[1];
        let xLen = Math.abs(point2.pageX - point1.pageX);
        let 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;
      this.eLen =e.touches.length;
      if(e.touches.length > 1) {
        let xLen = Math.abs(e.touches[0].pageX - e.touches[1].pageX);
        let yLen = Math.abs(e.touches[0].pageY - e.touches[1].pageY);
        let touchDistance = this._getDistance(xLen,yLen);
        if(this.touchDistance) {
          let pinchScale = touchDistance / this.touchDistance;
          this.previousPinchScale = pinchScale>1? pinchScale: 1;
          
        }

      }
    },
    _getTime(){
      return new Date().getTime(); 
    },
    touchend(e){
      let timestamp = this._getTime();
      if(this.moveX !== null && Math.abs(this.moveX - this.startX) > 10 ||
      this.moveY !== null && Math.abs(this.moveY - this.startY) > 10){
        
        if(timestamp - this.startTime < 500 && this.eLen>=2) {//手指移动的位移要大于10像素并且手指和屏幕的接触时间要短于500毫秒
          if(this.previousPinchScale > 1){
            this.zoomIn();
          }else{
            this.zoomOut();
          }
         
          this.eLen = 0;
        }
      }
    },
    zoomIn() {
      if (this.pdfViewer.isInPresentationMode) {
        return;
      }
      var newScale = this.pdfViewer.currentScale;
     
      if(newScale < this.MAX_SCALE){
        newScale = (newScale * this.DEFAULT_SCALE_DELTA).toFixed(2);
        
        newScale = Math.ceil(newScale * 10) / 10;
        
        newScale = Math.min(this.MAX_SCALE, newScale);
      }

      this.pdfViewer.currentScaleValue = newScale;
    },
    zoomOut() {
      if (this.pdfViewer.isInPresentationMode) {
        return;
      }

      var newScale = this.pdfViewer.currentScale;
      if(newScale > this.MIN_SCALE){
        newScale = (newScale / this.DEFAULT_SCALE_DELTA).toFixed(2);
        newScale = Math.floor(newScale * 10) / 10;
        newScale = Math.max(this.MIN_SCALE, newScale);
      }
      
      this.pdfViewer.currentScaleValue = newScale;
    },
    zoomReset() {
      if (this.pdfViewer.isInPresentationMode) {
        return;
      }
  
      this.pdfViewer.currentScaleValue = this.DEFAULT_SCALE_VALUE;
    },
  
    renderPdf() {
      if (!this.url) { return }
      // Loading document.
      if (this.pdfViewer === null || this.pdfLinkService === null) {
        return
      }
      if (this.loadingTask !== null) {
        this.loadingTask.destroy()
        this.loadingTask = null
      }
      this.loadingTask = window.pdfjsLib.getDocument({
        cMapUrl: this.CMAP_URL,
        cMapPacked: true,
        url: this.url,
      });
      return this.loadingTask.promise.then((pdfDocument) => {
        if (pdfDocument.loadingTask.destroyed || !this.url) { return }
        this.pdfViewer.setDocument(pdfDocument)
        this.pdfLinkService.setDocument(pdfDocument, null);
        this.loadingTask = null
      }).catch(error => {
        console.log(error)
      });
    }
  },
  mounted() {
    this.pdfLibInit().then(() => {
      this.renderPdf()
    })
  },
  watch: {
    url() {
      // 如果存在pdfViewer则取消渲染
      if(this.pdfViewer) {
        this.pdfViewer._cancelRendering()
      }
      this.renderPdf()
    }
  }
}
</script>

 

Logo

前往低代码交流专区

更多推荐