【问题标题】:Render MathJax into PDF将 MathJax 渲染成 PDF
【发布时间】:2017-08-04 18:44:03
【问题描述】:

我花了好几天的时间来研究如何在开源项目Writing 上仅在客户端(使用几个库,如 jsPDF 等)将 MathJax 呈现为 PDF。我尝试了许多不同的选择,但都没有成功。

这是我最近一次尝试中显示问题的代码,基于this answer。

  MathJax.Hub.Config({ tex2jax: {inlineMath: [["$","$"],["\\(","\\)"]]} });

document.getElementById("getPdf").addEventListener("click", getPdf);

function getPdf() {
  var svg = document.getElementById('main').innerHTML;
  if (svg)
    svg = svg.replace(/\r?\n|\r/g, '').trim();

  var canvas = document.createElement('canvas');
  var context = canvas.getContext('2d');

  context.clearRect(0, 0, canvas.width, canvas.height);
  canvg(canvas, svg);

  var imgData = canvas.toDataURL('image/png');

  var doc = new jsPDF('p', 'pt', 'a4');
  doc.addImage(imgData, 'PNG', 40, 40, 75, 75);
  doc.save('test.pdf');
}  
<script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML-full"></script>
<script src="https://cdn.rawgit.com/canvg/canvg/master/canvg.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.2.61/jspdf.min.js"></script>

<p id="main">
When $a \ne 0$, there are two solutions to \(ax^2 + bx + c = 0\) and they are
$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$
</p>

<button id="getPdf">Get PDF</button>

问题:

如何仅在客户端将 HTML + MathJax 内容呈现为 PDF?

【问题讨论】:

标签: javascript pdf svg mathjax jspdf


【解决方案1】:

我的简短回答是:不要这样做。

长答案是您可以完成这项工作,但结果将不如提供打印样式表并让用户将输出保存为 PDF。对于初学者,您将创建一个包含单个(可能很大)PNG 的 PDF;这对打印来说会很糟糕。

您的代码的主要问题是canvg 只能处理SVG 内容,不能处理任意Web 内容,因此您需要使用其他工具。

但通常在画布元素中注入 HTML 内容是有限制的 (for security reasons)。

最后,您需要强制关闭 MathJax 的 AssistiveMML 扩展以避免重复内容。

下面是一个 sn-p,但由于上述安全原因,它在 SO 上失败了;不过你可以在codepen 上试试。

MathJax.Hub.Queue(function (){
  var canvas = document.getElementById("canvas");
  var main = document.getElementById("main");
  rasterizeHTML.drawHTML(main.outerHTML,canvas);

})
document.getElementById("getPdf").addEventListener("click", getPdf);

function getPdf() {
  var imgData = canvas.toDataURL('image/png');

  var doc = new jsPDF('p', 'pt', 'a4');
  doc.addImage(imgData, 'PNG', 40, 40, 400, 200);
  doc.save('test.pdf');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.2.61/jspdf.min.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js"],
  "AssistiveMML": {
    disabled: true
  },
  SVG: {
    addMMLclasses: true,
    useGlobalCache: false
  },
  });
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_SVG-full"></script>
<script   src="https://cdnjs.cloudflare.com/ajax/libs/rasterizehtml/1.2.4/rasterizeHTML.allinone.js"></script>
<p id="main">
When \(a \ne 0\), there are two solutions to \(ax^2 + bx + c = 0\) and they are
$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$
</p>
<h1>As canvas</h1>
    <canvas id="canvas" width="400" height="200"></canvas>

<button id="getPdf">Get PDF</button>

【讨论】:

  • 感谢您的回答。它似乎无法正确渲染(即使在 Codepen 中,“作为画布”之后的部分也仅使用水平线而不是数学渲染)。看起来like this。
  • 别的东西:我真的不想把整个东西渲染成一个大的PNG。实际上,我想将文本保留为文本,仅将 MathJax 部分呈现为 PNG 或 SVG,然后可以将其保存为带有 jsPDF 或类似库的 PDF。
  • 最后一件事:如果我们放眼大局,我真的不同意“不要这样做”。 应该有一个解决方案:我想要here in this page 是让用户在左边写markdown 和math。 应该可以导出为 PDF。我的意思是,从用户的角度来看。用户应该能够导出为 PDF :) 所以我必须找到如何做到这一点... ;)
  • 带白线的渲染表明配置没有被拾取。我注意到一个尾随逗号并修复它;看看这是否有帮助或在现代浏览器中尝试本地副本
  • 可以解决大的 PNG 问题,但 jsPDF 是一个低级库,允许您将内容放置在 PDF 画布上。您必须在 jsPDF 之上重新实现许多浏览器布局功能才能完成。
猜你喜欢
  • 2013-02-11
  • 2013-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多