FranckFreiburger / vue-pdf

vue.js pdf viewer
MIT License
2.21k stars 520 forks source link

text selection available #72

Open Mik-A opened 6 years ago

Mik-A commented 6 years ago

How do I get a working search field? Is it possible? How about text selection?

chrisgillis commented 6 years ago

I'm also looking for information on how to get the text selection layer working. Any advice?

Dorothysun commented 5 years ago

Same. Also trying to do text selection on the pdf file being generated. Any update?

alexfok007 commented 5 years ago

Same request. Also want text selection. Thanks

halower commented 5 years ago

Same request. Also want text selection. Thanks

zealot128 commented 5 years ago

I followed this guide:

https://usefulangle.com/post/90/javascript-pdfjs-enable-text-layer

I had to make adjustment, because i don't use the pdf scale, but just manipulated width of the surrounding div and i use v-dragscroll to allow moving in a zoomed pdf.


<template>
<!-- ... some buttons to zoom, switch pages, rotate etc. and activate textSelectionEnabled ... !-->

<!-- wrapper div with position relative outside, using v-dragscroll to use mouse/touch device to move inside doc -->
<div 
    v-dragscroll='!textSelectionEnabled' 
    :class='{"zoom-active": zoom > 40, "text-selection": textSelectionEnabled, "pdf-viewer-wrapper": true }' 
     style='position: relative'>

  <vue-pdf ... 
      ref='pdf'  
     :style='{ width: zoom + "%" }'   
     :page='currentPage'
     @page-loaded='onPageLoad' class='pdf-main' />
  <!-- hidden text layer -->
  <div
       class="pdf-viewer--text-layer"
       ref='textLayer'
       :style='{left: textLayerViewport.left + "px", top: textLayerViewport.top + "px", height: textLayerViewport.height + "px", width: textLayerViewport.width + "px" }')
   />
</div>
</template>

</template>

<script>
const PDFJS = require('pdfjs-dist/build/pdf.js');

export default {
   data() { 
     return {
   textSelectionEnabled: false,
   zoom: 40,
   currentPage: 1,
    textLayerViewport: {
       left: 0,
       top: 0,
       height: 0,
       width: 0,
     }
  }},
   // when changing zoom = width of the wrapper div, rerun the text layer
  watch: { zoom() {   setTimeout(() => this.onPageLoad(), 150) } },
  methods: {
    onPageLoad() {
     // currently, vue-pdf componentfactory wrapper does not export a function to get one specific page, so iterating over all
     this.$refs.pdf.pdf.forEachPage((page) => {
      if (page.pageIndex === this.currentPage - 1) {
        return page.getTextContent()
           .then(content => {
           const rect = this.$refs.pdf.$refs.canvas.getBoundingClientRect()
           this.$refs.textLayer.innerHTML = ""
           this.textLayerViewport.left = rect.left + document.body.scrollLeft
           this.textLayerViewport.top = rect.top + document.body.scrollTop
           // because position: relative, the left and top are correct by default
           this.textLayerViewport.left = 0
           this.textLayerViewport.top = 0
           this.textLayerViewport.height = this.$refs.pdf.$refs.canvas.height
           this.textLayerViewport.width = this.$refs.pdf.$refs.canvas.width
           // get the REAL scale comparing the current canvas width and the "normal" Viewport width at a scale of 1.0
           const scale = this.$refs.pdf.$refs.canvas.width / page.getViewport(1).width
           const viewport = page.getViewport(scale);
           PDFJS.renderTextLayer({
             textContent: content,
             container: this.$refs.textLayer,
               viewport: viewport,
               textDivs: []
             });
           })
       }
    })
 }

</script>

<style lang='scss'>
  .pdf-viewer-wrapper {
    overflow: hidden;
    overflow-y: scroll;
    max-height: 80vh;
    background: #444;
    overflow-scrolling: touch;
    &::-webkit-scrollbar {
      display: none;
    }
    &.zoom-active {
      cursor: grab;
    }
    &.text-selection {
      cursor: normal
    }
  }
  .pdf-main {
    margin: 30px auto;
  }
  .pdf-viewer--text-layer {
    margin: 30px auto;
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    overflow: hidden;
    opacity: 0.2;
    line-height: 1.0;
    ::selection {
      background-color: #FFA;
    }
  }

  .pdf-viewer--text-layer > div {
    color: transparent;
    position: absolute;
    white-space: pre;
    cursor: text;
    transform-origin: 0% 0%;
  }

  </style>
jlpereira commented 4 years ago

Is there any intention to implement this?

michaelsogos commented 3 years ago

Dear @FranckFreiburger

Did you find time to implement text selection on canvas or with a text layer over it?