如何在 Chrome 中 HTML 中旋转 SVG 中的 Pdf.js canvas 输出?

How to rotate Pdf.js canvas output in SVG in HTML in Chrome?

我正在开发一个 Web 应用程序,其 HTML 用户界面在某些时候涉及 SVG 图形。该 SVG 的一部分会进行各种变换,例如旋转。

在转换后的 SVG 图形中,我现在需要显示一个 PDF 文件(的第一页)。为此,我使用 <foreignObject> element that contains an HTML body with a <canvas> element that can serve as the target of the PDF.js library1.

这是一个包含 <g> element 并对其进行旋转变换的最小示例。 <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 中,这符合预期:

然而,在 Chrome 74 中,canvas 显示了 PDF 第一页(而不是其左上角)中看似任意的矩形,并且此输出未旋转,或者:

有什么方法可以解决此问题并旋转 PDF 以在 Chrome 中显示在我的 SVG 中?


1:不知何故,无论我查看什么资源,如何在 JavaScript 中呈现 PDF 的问题似乎总是指向这个库。此外,根据我在 the library's website 上阅读的内容,SVG 渲染器仍在进行中,因此不能在客户可以上传任意 PDF 内容的地方使用。

我已经遇到过类似的问题。可能是为了性能,在 chrome - canvas 中使用不是从 SVG 派生的独立上下文。 您可以改用 img 并将 pdf 渲染到隐藏的 canvas.

<!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>