vue2 解决pdf.js 渲染pdf时 划词选中 不准不流畅问题

 原本我使用的 是 vue-pdf-embed 的这个组件 后来 发现这个组件 对应vue2 的版本 可能太过于滞后了,里面的pdf.js大概率是2.x版本左右。这会导致我们渲染出来的部分pdf文件 启用textLayer会有文字排布不对甚至是文本层位置偏移 的大问题,如果对 划词翻译 或者渲染pdf上的文本层没有要求 只需要做简单的pdf渲染 建议使用 vue-pdf-embed 会快很多

 这里 给一下 vue-pdf-embed相关模块的使用流程 链接:

vue-pdf-embed@1

这里引入了cMapUrl 字体资源 用的 2.2.228版本 用其他2.x版本的字体资源应该没问题 如果低于或者高于 这个版本 会出现 日文、韩文 或者特殊语言的pdf 渲染不出来,cMapPacked 属性需要设置true 不然不生效。

<div v-for="(item,index) in pdfList"  :ref="'child'+index" :key="index" class="pdf">
          <VuePdfEmbed
            :source="{
                cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.2.228/cmaps/',
                 cMapPacked: true,
                url: myUrl,
              }" 
            :page="parseInt(item)"
            :textLayer="true"
            @loaded="loaded"
            @rendering-failed="renderingFailed($event,index)"
            @loading-failed="loadingFailed($event,index)"
          />
        </div> 

接下来 讲一下 pdf.js渲染pdf 这里 由于pdf.js 引入 vue2 时 是作为模块引入的 也就是 pdf-dist 模块,基本3.x版本以上 就都是vue3才可以使用了,我们项目引入 pdf-dist@3.x时就会npm 失败 。因此选择直接在public 的index.html  直接引入你想要使用的 pdf.js cdn资源 以pdf_viewer.min.css 样式。

 <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.5.141/pdf.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.5.141/pdf_viewer.min.css" />

另外在需要渲染pdf的vue页面 获取一下内置的对象

const PDFJS = window['pdfjs-dist/build/pdf'];
PDFJS.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.5.141/pdf.worker.min.js';

然后就是渲染pdf的相关方法 ,因为我封装了一个渲染组件  所以在最后面 当第一页pdf代码执行末尾 我emit 了一个事件 返回给父组件 代表渲染结束。

       showPDF(pdf_url) {
          this.loading = true
          var that = this
          let idName = 'canvas-pdf-'
          PDFJS.getDocument({ url: pdf_url , cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@3.5.141/cmaps/',cMapPacked: true}).promise.then(function (pdf_doc) {
            that.pdfObj = pdf_doc;
            console.log("pdf_doc",pdf_doc );
            that.totals = that.pdfObj['_pdfInfo'].numPages;
            console.log("pdf_doc2",pdf_doc,'this.totals ',that.totals );
            // Show the first page    0.00077 每px 的scalc 比例
              let pdfContainer = document.getElementById('pdf-container')
              let scale;
              that.pdfObj.getPage(1).then(p=>{
                console.log('pdfContainer',pdfContainer.clientWidth,p.getViewport({ scale: 1.03 }).width);
                let containerWidth = pdfContainer.clientWidth;
                scale = containerWidth / p.getViewport({ scale: 1.03 }).width;
                 for (let i = 1; i <= that.totals; i++) {
                      that.pdfObj.getPage(i).then(async (page) => {
                        let canvas = document.getElementById(idName + i)
                        let __CANVAS_CTX = canvas.getContext('2d')
                        let viewport = page.getViewport({
                            scale:scale,//that.windowWidth * 0.0007482 //1.18,
                          });
                          console.log('that.windowWidth * 0.0007482',that.windowWidth * 0.0007482);
                          // viewport.width = pdfContainer.clientWidth;
                          canvas.height = viewport.height;
                          canvas.width = viewport.width;

                          var renderContext = {
                            canvasContext: __CANVAS_CTX,
                            viewport: viewport
                          };
                          page.render(renderContext).promise.then(function () {
                            return page.getTextContent();
                          }).then(function (textContent) {
                            let pageDiv = document.getElementById(`page-${i}`)
                            
                            var thisNode = document.getElementById('text-layer'+i);
                            if(thisNode){
                              pageDiv.removeChild(thisNode)
                            }
                            const textLayerDiv = document.createElement('div')
                            textLayerDiv.setAttribute('id', 'text-layer'+i)
                            textLayerDiv.setAttribute('class', 'textLayer')
                            // 将文本图层div添加至每页pdf的div中
                            pageDiv.appendChild(textLayerDiv)
                            // Clear HTML for text layer
                            $("#text-layer"+i).html('');

                            // Assign the CSS created to the text-layer element
                            console.log('viewport.scale',viewport.scale);
                            
                            document.getElementById('text-layer'+i).style.setProperty('--scale-factor', viewport.scale);
                            $("#text-layer"+i).css({ left: 0 + 'px', top: 0 + 'px'});
                            // Pass the data to the method for rendering of text over the pdf canvas.
                            PDFJS.renderTextLayer({
                              textContentSource: textContent,
                              container: $("#text-layer"+i).get(0),
                              viewport: viewport,
                              textDivs: []
                            });
                            if(i==1){
                              // 渲染成功
                              that.loading = false
                              that.$emit('isOverImg',{type:'1',flag:false,isLoadingOver:true})
                            }
                          });
                      })
                    }
              })
              
              
          }).catch(function (error) {
            // 渲染失败
            that.loading = false
            that.$message({message:"文件渲染失败,请刷新浏览器重试",type:'error',showClose:true})
          });
        },

 <div class="wrapper" id="pdf-container"  @mouseleave="mouseleave" >
              <div v-for="item in totals" :id="`page-${item}`" :key="item" class="pdf-box" @mouseup="handleMouseSelect"  @mousedown="mousedown($event)" :draggable="false" @mousemove="mousemove($event,item)">
                <canvas :id="'canvas-pdf-' + item" class="canvas-pdf"></canvas>
              </div>
            </div>

以上 就是vue2 引入pdf.js做渲染 用这种方式渲染出来的pdf 不仅文本层排列整齐 并且划词 也会比vue-pdf-embed 效果好一些。  

@mouseup="handleMouseSelect"  

@mousedown="mousedown($event)" :draggable="false"

@mousemove="mousemove($event,item)"

这几个事件 是根治 pdf.js  划词准确性 以及流畅性的 方法。这一章先讲到这里,有任何问题可关注私信我,或者加我QQ私聊问我,后续有空 补充完整 pdf.js 优化划词选中 相关示例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值