在 React 中使用 OffScreenCanvas 将 HTML 转换为 PDF

Convert HTML to PDF Using OffScreenCanvas in React

好的,所以这个问题是不言自明的。

目前,我正在做以下事情

  1. 使用 html2canvas npm 包将我的 html 转换为 canvas.
  2. 正在将 Canvas 转换为图像
         canvas.toDataURL("image/png");
  1. 使用 jsPDF 在一些操作后使用此图像创建 pdf。

所以基本上所有这个过程都是 CPU 密集的并且会导致页面无响应。

我正在尝试将流程卸载给网络工作者,但我无法将 HTML 节点或 Canvas 元素发送到我的工作线程。

因此,尝试使用 OffScreenCanvas,但我不知道如何继续使用它。

第一步无法在Web-Worker中完成。您需要访问 DOM 才能绘制它,而工人无权访问 DOM.

第二步 可以在 OffscreenCanvas 上完成,html2canvas 接受 { canvas } 参数,您还可以将其设置为 OffscreenCanvas.
但是一旦你从 OffscreenCanvas 获得上下文,你就不能再传输它,所以你将无法将 OffscreenCanvas 传递给Worker 和你不会从中获得任何好处,因为一切仍将在 UI 线程上完成。
所以我们能做的最好的事情就是让 html2canvas 初始化一个 HTMLCanvasElement,在上面绘制,然后将其转换为 Blob 中的图像。 Blob 可以在没有任何复制成本的情况下遍历领域,并且 toBlob() 方法可以异步完成其压缩部分。

第三步可以在Worker中完成,因为this PR

我不知道反应所以你将不得不重写它,但这是一个简单的 JS 实现:

script.js

const dpr = window.devicePixelRatio;
const worker = new Worker( "worker.js" );
worker.onmessage = makeDownloadLink;
worker.onerror = console.error;

html2canvas( target ).then( canvas => {
  canvas.toBlob( (blob) => worker.postMessage( {
    source: blob,
    width: canvas.width / dpr, // retina?
    height: canvas.height / dpr // retina?
  } ) );
} );

worker.js

importScripts( "https://unpkg.com/jspdf@latest/dist/jspdf.umd.min.js" );
onmessage = ({ data }) => {
  const { source, width, height } = data;
  const reader = new FileReaderSync();
  const data_url = reader.readAsDataURL( source );
  const doc = new jspdf.jsPDF( { unit: "px", format: [ width, height ], orientation: width > height ? "l" : "p" });
  doc.addImage( data_url, "PNG", 0, 0, width, height, { compression: "NONE" } );
  postMessage( doc.output( "blob" ) );
};

而且由于 StackSnippet 过度保护的 iframe 确实会破坏 html2canvas,这里是 outsourced live example.