MathJax 3 中 MathJax 未定义或 tex2svg 不可用怎么办?
数据小陈
原因
tex-svg.js 使用 async 加载时,浏览器不会等它执行完再运行页面中的其他 JavaScript。此时调用 MathJax.tex2svg(tex),可能因 MathJax 尚未加载而报错 MathJax is not defined。如果加载的组件不包含 SVG 输出功能,或者在 MathJax 启动完成前调用,也可能出现 MathJax.tex2svg 不可用的情况。
原代码还有一个问题:base64 是字符串,不能调用 addEventListener,也不能传给 ctx.drawImage()。应先创建 Image 对象并加载 SVG,再将图像绘制到 canvas 上。
解决方法
移除 MathJax 脚本上的 async,让浏览器按页面顺序加载脚本。然后等待 MathJax 的启动 Promise 完成,再转换公式。SVG 加载到 Image 后,就可以绘制到 canvas:
<canvas id="surface">Canvas not Supported</canvas>
<script
id="MathJax-script"
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
</script>
<script>
(async () => {
await MathJax.startup.promise;
const canvas = document.getElementById("surface");
const ctx = canvas.getContext("2d");
canvas.width = 202;
const tex = "F=ma";
const container = MathJax.tex2svg(tex);
const svg = container.querySelector("svg");
if (!svg) {
throw new Error("MathJax 没有生成 SVG");
}
const svgText = new XMLSerializer().serializeToString(svg);
const svgUrl = URL.createObjectURL(
new Blob([svgText], { type: "image/svg+xml;charset=utf-8" })
);
const image = new Image();
image.onload = () => {
ctx.drawImage(image, 105, 15, 102.3, 23.93);
URL.revokeObjectURL(svgUrl);
};
image.onerror = () => {
URL.revokeObjectURL(svgUrl);
console.error("SVG 图片加载失败");
};
image.src = svgUrl;
})().catch(console.error);
</script>
这里的 tex-svg.js 提供 tex2svg。await MathJax.startup.promise 会等 MathJax 启动完成后再调用它。代码使用 URL.createObjectURL() 创建临时的 SVG 图片地址,并在图片加载后将其绘制到 canvas。
注意事项
- 如果必须保留
async,应等 MathJax 脚本加载并完成启动后,再执行转换逻辑。不要假设后续代码运行时全局对象已经就绪。 ctx.drawImage()接收已加载的图像等绘图源,不能直接接收 Base64 字符串。也可以将 SVG 编码为 data URL 后赋给image.src,但仍要等待image.onload。- 页面里有多个公式时,记得在对应图片加载后及时释放重复生成的对象 URL。
备注:内容仅供参考。
