Подтвердить что ты не робот

Есть ли минималистический образец PDF.js, который поддерживает выбор текста?

Я пытаюсь PDF.js.

Моя проблема в том, что демонстрация Hello World не поддерживает выбор текста. Он будет рисовать все на холсте без текстового слоя. официальная версия PDF.js поддерживает выбор текста, но код слишком сложный. Мне было интересно, есть ли у кого-то минималистичное демо с текстовым слоем.

4b9b3361

Ответ 1

Я передал пример в репозиторий Mozilla pdf.js, и он доступен в каталоге examples.

Исходный пример, который я сделал для pdf.js, больше не существует, но я считаю, что этот пример демонстрирует выбор текста. Они очистили и реорганизовали pdf.js, и поэтому логика выбора текста инкапсулируется внутри текстового слоя, который может быть создан с помощью factory.

В частности, PDFJS.DefaultTextLayerFactory выполняет настройку основного материала для выбора текста.


Следующий пример устарел; только оставляя его здесь по историческим причинам.

Я боролся с этой проблемой в течение 2-3 дней, но, наконец, понял. Здесь - это скрипка, в которой показано, как загрузить PDF с включенным выбором текста.

Трудность в выяснении этого заключалась в том, что логика выбора текста была переплетена с кодом зрителя (viewer.js, viewer.html, viewer.css). Мне пришлось выпустить соответствующий код и CSS, чтобы заставить это работать (на этот файл JavaScript ссылается файл, вы также можете проверить его здесь). Конечным результатом является минимальная демонстрация, которая должна оказаться полезной. Для правильного выбора отбора CSS, который находится в viewer.css, также чрезвычайно важен, поскольку он устанавливает стили CSS для div, которые в конечном итоге создаются, а затем используются для обработки текста.

Тяжелый подъем выполняется объектом TextLayerBuilder, который фактически обрабатывает создание выделения div s. Вы можете видеть вызовы этого объекта из viewer.js.

В любом случае, здесь код, включая CSS. Имейте в виду, что вам все равно понадобится файл pdf.js. У моей скрипки есть ссылка на версию, которую я создал из репозитория Mozilla GitHub для pdf.js. Я не хотел напрямую ссылаться на версию репо, поскольку они постоянно ее разрабатывают, и это может быть нарушено.

Итак, без дальнейших церемоний:

HTML:

<html>
    <head>
        <title>Minimal pdf.js text-selection demo</title>
    </head>

    <body>
        <div id="pdfContainer" class = "pdf-content">
        </div>
    </body>
</html>

CSS

.pdf-content {
    border: 1px solid #000000;
}

/* CSS classes used by TextLayerBuilder to style the text layer divs */

/* This stuff is important! Otherwise when you select the text, the text in the divs will show up! */
::selection { background:rgba(0,0,255,0.3); }
::-moz-selection { background:rgba(0,0,255,0.3); }

.textLayer {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    color: #000;
    font-family: sans-serif;
    overflow: hidden;
}

.textLayer > div {
    color: transparent;
    position: absolute;
    line-height: 1;
    white-space: pre;
    cursor: text;
}

.textLayer .highlight {
    margin: -1px;
    padding: 1px;

    background-color: rgba(180, 0, 170, 0.2);
    border-radius: 4px;
}

.textLayer .highlight.begin {
    border-radius: 4px 0px 0px 4px;
}

.textLayer .highlight.end {
    border-radius: 0px 4px 4px 0px;
}

.textLayer .highlight.middle {
    border-radius: 0px;
}

.textLayer .highlight.selected {
    background-color: rgba(0, 100, 0, 0.2);
}

JavaScript:

//Minimal PDF rendering and text-selection example using pdf.js by Vivin Suresh Paliath (http://vivin.net)
//This fiddle uses a built version of pdf.js that contains all modules that it requires.
//
//For demonstration purposes, the PDF data is not going to be obtained from an outside source. I will be
//storing it in a variable. Mozilla viewer does support PDF uploads but I haven't really gone through
//that code. There are other ways to upload PDF data. For instance, I have a Spring app that accepts a
//PDF for upload and then communicates the binary data back to the page as base64. I then convert this
//into a Uint8Array manually. I will be demonstrating the same technique here. What matters most here is
//how we render the PDF with text-selection enabled. The source of the PDF is not important; just assume
//that we have the data as base64.
//
//The problem with understanding text selection was that the text selection code has heavily intertwined
//with viewer.html and viewer.js. I have extracted the parts I need out of viewer.js into a separate file
//which contains the bare minimum required to implement text selection. The key component is TextLayerBuilder,
//which is the object that handles the creation of text-selection divs. I have added this code as an external
//resource.
//
//This demo uses a PDF that only has one page. You can render other pages if you wish, but the focus here is
//just to show you how you can render a PDF with text selection. Hence the code only loads up one page.
//
//The CSS used here is also very important since it sets up the CSS for the text layer divs overlays that
//you actually end up selecting. 
//
//For reference, the actual PDF document that is rendered is available at:
//http://vivin.net/pub/pdfjs/TestDocument.pdf

var pdfBase64 = "..."; //should contain base64 representing the PDF

var scale = 1; //Set this to whatever you want. This is basically the "zoom" factor for the PDF.

/**
 * Converts a base64 string into a Uint8Array
 */
function base64ToUint8Array(base64) {
    var raw = atob(base64); //This is a native function that decodes a base64-encoded string.
    var uint8Array = new Uint8Array(new ArrayBuffer(raw.length));
    for(var i = 0; i < raw.length; i++) {
        uint8Array[i] = raw.charCodeAt(i);
    }

    return uint8Array;
}

function loadPdf(pdfData) {
    PDFJS.disableWorker = true; //Not using web workers. Not disabling results in an error. This line is
                                //missing in the example code for rendering a pdf.

    var pdf = PDFJS.getDocument(pdfData);
    pdf.then(renderPdf);                               
}

function renderPdf(pdf) {
    pdf.getPage(1).then(renderPage);
}

function renderPage(page) {
    var viewport = page.getViewport(scale);
    var $canvas = jQuery("<canvas></canvas>");

    //Set the canvas height and width to the height and width of the viewport
    var canvas = $canvas.get(0);
    var context = canvas.getContext("2d");
    canvas.height = viewport.height;
    canvas.width = viewport.width;

    //Append the canvas to the pdf container div
    jQuery("#pdfContainer").append($canvas);

    //The following few lines of code set up scaling on the context if we are on a HiDPI display
    var outputScale = getOutputScale();
    if (outputScale.scaled) {
        var cssScale = 'scale(' + (1 / outputScale.sx) + ', ' +
            (1 / outputScale.sy) + ')';
        CustomStyle.setProp('transform', canvas, cssScale);
        CustomStyle.setProp('transformOrigin', canvas, '0% 0%');

        if ($textLayerDiv.get(0)) {
            CustomStyle.setProp('transform', $textLayerDiv.get(0), cssScale);
            CustomStyle.setProp('transformOrigin', $textLayerDiv.get(0), '0% 0%');
        }
    }

    context._scaleX = outputScale.sx;
    context._scaleY = outputScale.sy;
    if (outputScale.scaled) {
        context.scale(outputScale.sx, outputScale.sy);
    }     

    var canvasOffset = $canvas.offset();
    var $textLayerDiv = jQuery("<div />")
        .addClass("textLayer")
        .css("height", viewport.height + "px")
        .css("width", viewport.width + "px")
        .offset({
            top: canvasOffset.top,
            left: canvasOffset.left
        });

    jQuery("#pdfContainer").append($textLayerDiv);

    page.getTextContent().then(function(textContent) {
        var textLayer = new TextLayerBuilder($textLayerDiv.get(0), 0); //The second zero is an index identifying
                                                                       //the page. It is set to page.number - 1.
        textLayer.setTextContent(textContent);

        var renderContext = {
            canvasContext: context,
            viewport: viewport,
            textLayer: textLayer
        };

        page.render(renderContext);
    });
}

var pdfData = base64ToUint8Array(pdfBase64);
loadPdf(pdfData);    

Ответ 2

Поскольку это старый вопрос и старый принятый ответ, чтобы он работал с последними версиями PDF.JS, вы можете использовать это решение

http://www.ryzhak.com/converting-pdf-file-to-html-canvas-with-text-selection-using-pdf-js

Вот код, который они использовали: Включите следующие CSS и скрипты из кода PDF.js

<link rel="stylesheet" href="pdf.js/web/text_layer_builder.css" />
<script src="pdf.js/web/ui_utils.js"></script>
<script src="pdf.js/web/text_layer_builder.js"></script>

используйте этот код для загрузки PDF:

PDFJS.getDocument("oasis.pdf").then(function(pdf){
    var page_num = 1;
    pdf.getPage(page_num).then(function(page){
        var scale = 1.5;
        var viewport = page.getViewport(scale);
        var canvas = $('#the-canvas')[0];
        var context = canvas.getContext('2d');
        canvas.height = viewport.height;
        canvas.width = viewport.width;

        var canvasOffset = $(canvas).offset();
        var $textLayerDiv = $('#text-layer').css({
            height : viewport.height+'px',
            width : viewport.width+'px',
            top : canvasOffset.top,
            left : canvasOffset.left
        });

        page.render({
            canvasContext : context,
            viewport : viewport
        });

        page.getTextContent().then(function(textContent){
           console.log( textContent );
            var textLayer = new TextLayerBuilder({
                textLayerDiv : $textLayerDiv.get(0),
                pageIndex : page_num - 1,
                viewport : viewport
            });

            textLayer.setTextContent(textContent);
            textLayer.render();
        });
    });
});