pdfjs的setDocument 方式在移动端的手势缩放功能实现

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

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>

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: PDF.js 是一个用于在浏览器中显示 PDF 文件的 JavaScript 库。它提供了一种简单、快速和易于使用的方法来展示并与 PDF 文档进行交互。 要实现手势缩放,在 PDF.js 中有几个步骤需要遵循: 1. 监听 touchstart、touchmove 和 touchend 事件,以跟踪用户手势操作。 2. 在 touchstart 事件中记录触摸点的起始位置。 3. 在 touchmove 事件中计算触摸点的移动距离,并基于移动的距离来改变 PDF 页面的缩放级别。 4. 在 touchend 事件中清除触摸点的起始位置和移动距离。 以下是一个简单的示例代码,用于实现手势缩放功能: ```javascript var touchStartX, touchStartY, touchMoveX, touchMoveY; var scale = 1; // 监听 touchstart 事件,记录触摸点的起始位置 document.addEventListener('touchstart', function(event) { var touch = event.touches[0]; touchStartX = touch.clientX; touchStartY = touch.clientY; }); // 监听 touchmove 事件,计算触摸点的移动距离并改变缩放级别 document.addEventListener('touchmove', function(event) { var touch = event.touches[0]; touchMoveX = touch.clientX; touchMoveY = touch.clientY; // 计算移动距离 var deltaX = touchMoveX - touchStartX; var deltaY = touchMoveY - touchStartY; // 根据移动距离计算缩放比例 var deltaDistance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); var newScale = scale + (deltaDistance / 1000); // 根据具体情况调整缩放速度 // 应用新的缩放级别 if (newScale > 0.5 && newScale < 5) { // 设置缩放的最大和最小限制 scale = newScale; document.getElementById('pdfContainer').style.transform = 'scale(' + scale + ')'; } }); // 监听 touchend 事件,清除触摸点的起始位置和移动距离 document.addEventListener('touchend', function() { touchStartX = null; touchStartY = null; touchMoveX = null; touchMoveY = null; }); ``` 在上面的示例代码中,我们可以看到监听了 touchstart、touchmove 和 touchend 事件,并在对应的事件处理程序中进行相应的操作。通过计算触摸点的移动距离,并基于移动的距离来改变 PDF 页面的缩放级别,从而实现手势缩放的效果。注意在实际应用中,你需要将上述代码与 PDF.js 相关的代码进行整合,以便在正确的地方应用缩放效果。 ### 回答2: PDF.js是一个基于JavaScript的开源PDF文档渲染器,它可以在现代浏览器中显示PDF文件。要实现手势缩放功能,需要按照以下步骤进行操作: 1. 获取PDF.js渲染容器的DOM元素,通常通过指定一个id或类名来获取。 2. 绑定触摸事件,监听用户的手势操作。 3. 在触摸开始事件中,获取用户的初始手指位置和当前缩放比例。 4. 在触摸移动事件中,根据手指的位置差异计算缩放差值,并更新当前缩放比例。 5. 将计算得到的缩放差值应用到PDF.js渲染容器上,实现缩放效果。 6. 在触摸结束事件中,清除手指位置和缩放比例等数据。 以下是一个简单实现手势缩放功能的例子: ```html <!DOCTYPE html> <html> <head> <title>PDF.js手势缩放示例</title> <style> #pdfContainer { width: 100%; height: 500px; } </style> </head> <body> <div id="pdfContainer"></div> <script src="pdfjs-dist/build/pdf.js"></script> <script> const container = document.getElementById('pdfContainer'); const scaleStep = 0.1; let initialScale = 1; let initialTouchDistance; function handleTouchStart(event) { if (event.touches.length === 2) { initialTouchDistance = Math.hypot( event.touches[0].pageX - event.touches[1].pageX, event.touches[0].pageY - event.touches[1].pageY, ); initialScale = container.style.transform ? parseFloat(container.style.transform.split(' ')[1]) : 1; } } function handleTouchMove(event) { if (initialTouchDistance && event.touches.length === 2) { const newTouchDistance = Math.hypot( event.touches[0].pageX - event.touches[1].pageX, event.touches[0].pageY - event.touches[1].pageY, ); const scaleDiff = (newTouchDistance - initialTouchDistance) * scaleStep; const newScale = initialScale + scaleDiff; container.style.transform = `scale(${newScale})`; container.style.transformOrigin = 'center'; } } function handleTouchEnd(event) { initialTouchDistance = null; } container.addEventListener('touchstart', handleTouchStart); container.addEventListener('touchmove', handleTouchMove); container.addEventListener('touchend', handleTouchEnd); </script> </body> </html> ``` 在上述示例中,我们通过监听触摸事件来实现手势缩放功能。 在触摸开始事件中,我们获取了初始手指位置和当前缩放比例,保存在变量`initialTouchDistance`和`initialScale`中。 在触摸移动事件中,我们计算出新的手指位置差异,通过乘以缩放步长得到缩放差值,并根据初始缩放比例计算出新的缩放比例。 最后,将新的缩放比例应用到PDF.js渲染容器上,实现手势缩放的效果。 在触摸结束事件中,我们清除了初始手指位置和缩放比例等数据,以便下一次手势操作的准备。 需要注意的是,以上示例仅演示了手势缩放操作的基本原理,具体在使用PDF.js的相关API时,可能需要进行适当的修改。 ### 回答3: pdf.js是一个用于在网页上显示PDF文件的JavaScript库。它提供了许多功能,包括手势缩放实现手势缩放的关键是处理用户的触摸事件。pdf.js使用了浏览器提供的Touch事件来实现手势缩放。以下是实现手势缩放的基本步骤: 1. 获取PDF页面的容器元素。在页面上,我们必须有一个用于显示PDF页面的容器元素。通过使用JavaScript代码获取该容器元素。 2. 监听触摸事件。使用`touchstart`、`touchmove`和`touchend`等触摸事件来监听用户的触摸行为。我们可以使用`addEventListener`方法来为这些事件绑定处理函数。 3. 计算手势缩放比例。在`touchmove`事件处理函数中,根据用户的手势移动距离计算缩放比例。我们可以使用`event.touches`来获取触摸点的信息,并根据触摸点的坐标来计算手势缩放比例。 4. 对PDF页面应用缩放。根据计算得到的缩放比例,使用CSS的`transform`属性对PDF页面进行缩放操作。我们可以通过修改容器元素的样式来实现这一目的。 5. 可选的,限制缩放范围。为了防止过大或过小的缩放,我们可以在计算得到的缩放比例上应用一些限制条件。例如,我们可以设置一个最小和最大缩放比例,并在应用缩放之前检查计算得到的比例是否超过这些限制。 通过以上步骤,我们可以实现pdf.js中的手势缩放功能。但需要注意的是,以上仅为一个基本的示例,实际应用中可能还涉及到更复杂的逻辑和处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值