Как повернуть вывод холста Pdf.js в SVG в HTML в Chrome? - PullRequest
0 голосов
/ 10 мая 2019

Я работаю над веб-приложением, пользовательский интерфейс HTML которого в какой-то момент использует графику SVG. Часть этого SVG подвергается различным преобразованиям, таким как вращение.

В этом преобразованном SVG-графике мне необходимо отобразить (первую страницу) файл PDF. Для этой цели я использую <foreignObject> элемент , который содержит тело HTML с <canvas> элементом , который может служить целью библиотеки PDF.js 1 .

Вот минимальный пример, который содержит <g> элемент с поворотным преобразованием на нем. Элемент <g> содержит обычный прямоугольник SVG для сравнения и приведенную выше конструкцию с выводом PDF.js:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.2.2/pdf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.2.2/pdf.worker.min.js"></script>
</head>
<body>
<svg width="800" height="600">
<rect width="100%" height="100%" fill="rgb(186, 224, 255)"/>
<g transform="rotate(-30) translate(10, 20) scale(1.5)">
    <rect x="100px" y="50px" width="100px" height="80px" stroke="red" fill="none"/>
    <foreignObject x="150px" y="300px" width="200" height="150">
        <xhtml:body margin="0px" padding="0px" width="200px" height="150px" border="1px solid black">
            <canvas width="200" height="150" id="cnv"/>
        </xhtml:body>
    </foreignObject>
</g>
</svg>
<script type="text/javascript">
pdfjsLib.getDocument('https://en.wikipedia.org/api/rest_v1/page/pdf/Canvas_element').promise.then(function (pdf) {
    return pdf.getPage(1);
}).then(function (page) {
    var viewport = page.getViewport({
        scale: 1
    });
    var pdfCanvas = document.getElementById('cnv');
    pdfCanvas.width = viewport.width;
    pdfCanvas.height = viewport.height;
    var renderCtx = {
        canvasContext: pdfCanvas.getContext('2d'),
        viewport: viewport
    };
    page.render(renderCtx);
});

</script>
</body>
</html>

В Firefox 66 это выглядит как ожидалось:

Firefox output

В Chrome 74, однако, холст показывает, казалось бы, произвольный прямоугольник с первой страницы PDF (а не его левый верхний угол), и этот вывод также не поворачивается:

Chrome output

Есть ли способ обойти эту проблему и повернуть PDF-файлы для отображения в моем SVG в Chrome?


1 : Каким-то образом, какой бы ресурс я ни смотрел, вопрос о том, как выводить PDF в JavaScript, неизменно, казалось, приводил к этой библиотеке. Кроме того, из того, что я прочитал на веб-сайте библиотеки , рендерер SVG все еще находится в стадии разработки и поэтому не может использоваться в местах, где клиенты могут загружать произвольный контент PDF.

1 Ответ

1 голос
/ 10 мая 2019

Я уже встречал подобную проблему.Вероятно, для производительности, в chrome - canvas используется изолированный контекст, который не является производным от SVG.Вы можете использовать img вместо этого и рендерить pdf на скрытый холст.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.2.2/pdf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.2.2/pdf.worker.min.js"></script>
</head>
<body>

<canvas width="200" height="150" id="cnv" style="position:absolute;left:-10000px"></canvas>

<svg width="800" height="600">
<rect width="100%" height="100%" fill="rgb(186, 224, 255)"/>
<g transform="rotate(-30) translate(10, 20) scale(1.5)">
    <rect x="100px" y="50px" width="100px" height="80px" stroke="red" fill="none"/>
    <foreignObject x="150px" y="300px" width="200" height="150">
        <xhtml:body margin="0px" padding="0px" width="200px" height="150px" border="1px solid black">
            <img id="img" x="150px" y="300px" width="200" height="150"/>
        </xhtml:body>
    </foreignObject>
</g>
</svg>
<script type="text/javascript">
pdfjsLib.getDocument('https://en.wikipedia.org/api/rest_v1/page/pdf/Canvas_element').promise.then(function (pdf) {
    return pdf.getPage(1);
}).then(function (page) {
    var viewport = page.getViewport({
        scale: 1
    });
    var pdfCanvas = document.getElementById('cnv');
    pdfCanvas.width = viewport.width;
    pdfCanvas.height = viewport.height;
    var renderCtx = {
        canvasContext: pdfCanvas.getContext('2d'),
        viewport: viewport
    };
    page.render(renderCtx);
});

// wait for page rendered, just use some pdf.js callback
setTimeout(function(){
    const cnv = document.getElementById('cnv');
    document.getElementById('img').src = cnv.toDataURL("image/png");
}, 2000);

</script>
</body>
</html>
...