❤️如何在前端渲染数学公式?❤️
前言
最近遇到一个需求,需要在网页上展示如下数学公式

经过一番查阅,思路如下:
- 通过
ocr将对应的公式图片识别成latex公式 - 使用
MathJax去渲染对应的latex公式
思路明确,直接开干

相关概念
什么是Latex?
latex是一种标记语言,我们不需要了解太多,只需要知道,它可以排版数学公式,可以把数学公式转化为latex语法.
通过一些开源的js库,就可以将复杂数学公式渲染到前端页面上
MathJax
MathJax 是一个开源的 JavaScript 库,可以解析LaTeX、MathML 和 AsciiMath 格式的数学表达式
有了上面两大神器,我们的需求就很好做了
OCR工具
因为我的公式需求不多,所以直接手动用OCR工具去转换了
- 公式识别工具:公式识别 (simpletex.cn)
相关依赖库
-
MathJax这个库用
npm去直接安装会有一些奇奇怪怪的问题,最终还是采用cdn引入的方式.
直接引入到index.html里面就可以
如果怕cdn不稳定,也可以直接下载下来,保存到public文件夹里面再引入

想要判断是否引入成功的话,只需要在控制台打印window.MathJax有挂载上去就是引入了
使用方式
初始化配置
在使用之前需要初始化MathJax的配置
window.MathJax.Hub.Config({
extensions: ['tex2jax.js'],
jax: ['input/TeX', 'output/HTML-CSS'],
showMathMenu: false,
tex2jax: {
inlineMath: [
['$', '$'],
['\\(', '\\)'],
],
displayMath: [
['$$', '$$'],
['\\[', '\\]'],
],
processEscapes: true,
},
'HTML-CSS': { availableFonts: ['TeX'] },
})
extensions: 数组,指定MathJax需要加载的扩展文件。这里加载的是tex2jax.js,这是一个将TeX格式转换为MathJax能够识别的格式的扩展。jax: 数组,指定MathJax处理数学公式的输入和输出格式。input/TeX表示输入格式是TeX,output/HTML-CSS表示输出格式是HTML-CSS,即MathJax将使用CSS来渲染数学公式。showMathMenu: 布尔值,设置是否显示数学公式的上下文菜单。这里设置为false,即不显示。tex2jax: 对象,包含了tex2jax扩展的配置项:inlineMath: 数组,定义了行内数学公式的界定符。这里定义了两种界定符:美元符号$...$和反斜杠加括号\(... \)。displayMath: 数组,定义了显示数学公式(即独占一行的数学公式)的界定符。这里定义了两种界定符:双美元符号$$...$$和反斜杠加双括号\[...\]。processEscapes: 布尔值,设置是否处理转义字符。如果为true,MathJax会处理如\和$等特殊字符的转义。
'HTML-CSS': 对象,配置HTML-CSS输出的一些选项。availableFonts数组指定了可用的字体。这里指定为['TeX'],即使用TeX字体。
更详细的配置可以去官网上面看:配置 MathJax — MathJax 3.2 文档
或者官方的github也会有一些例子
渲染公式
在一开始加载这个mathjax的时候他就会对网页上的公式进行一次渲染.但是我们在大多数情况下是需要动态渲染的,比如我只需要某一块内容渲染,或者某一时刻渲染.
这时候就需要用到他的api
window.MathJax.Hub.Queue
这个方法可以排队执行一些操作,比如排版、加载JS文件、动态配置,我们只需要第一个排版.
全局渲染
window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub])
-
Typeset: 重新排版文档或指定的元素中的数学公式。
-
window.MathJax.Hub:传不传都可以,默认会用这个作为上下文

局部渲染
window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, leftLatex.value])
前面的参数不变,最后第三个参数传要渲染的那个DOM的参数

完整代码
依赖引入
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>MathJax</title>
<style>
#app,
html,
body {
height: 100%;
width: 100%;
overflow: hidden;
}
</style>
</head>
<body>
<div id="app"></div>
<script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script>
import('/src/main.ts')
</script>
</body>
</html>
实现代码
<!-- 数学公式渲染需求 -->
<template>
<article class="latex-container">
<t-row>
<section ref="leftLatex" class="latex-container__show">
{{ latexStr }}
</section>
<section style="margin-left: 24px" class="latex-container__show">
{{ latexStr2 }}
</section>
</t-row>
<section style="display: flex; gap: 12px">
<t-button @click="startRenderingLeft">只渲染左边</t-button>
<t-button @click="startRendering">全局渲染</t-button>
</section>
</article>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const latexStr = ref<string>(`
对谷类、薯类、豆类、油料、草药、饲料、果蔬、茶菌、瓜果等农产品的实物量进行核算。
$$E_{pro1}=\\Sigma_{i=1}^nEPA_i$$
式中:
$$E_{pro1}——$$农产品总产量(t/a);
$$EPA_i——第i$$种产品的产量(t/a),
谷类、薯类、豆类、油料、草药、饲料数据来自国家统计局xx调查队;果蔬、茶菌、瓜果等数据来自市统计局。`)
const latexStr2 = ref<string>('$$\\int_a^bf(x)dx=c$$')
const leftLatex = ref(null)
const startRendering = () => {
window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub])
}
const startRenderingLeft = () => {
window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, leftLatex.value])
}
onMounted(() => {
if (!window.MathJax) return console.log('MathJax不存在')
window.MathJax.Hub.Config({
extensions: ['tex2jax.js'],
jax: ['input/TeX', 'output/HTML-CSS'],
showMathMenu: false,
tex2jax: {
inlineMath: [
['$', '$'],
['\\(', '\\)'],
],
displayMath: [
['$$', '$$'],
['\\[', '\\]'],
],
processEscapes: true,
},
'HTML-CSS': { availableFonts: ['TeX'] },
})
})
</script>
<style lang="scss" scoped>
.latex-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 24px;
&__show {
width: 500px;
height: 600px;
box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px;
background-color: #fff;
border-radius: 8px;
padding: 24px;
}
}
</style>
遇到的问题
如果出现,有些符号无法渲染,需要检查一下是不是需要转义
const latexStr2 = ref<string>('$$\\int_a^bf(x)dx=c$$')
比如这个公式,如果上面的公式变成
const latexStr2 = ref<string>('$$\int_a^bf(x)dx=c$$')
就会导致
这个符号渲染不出来
转载自:https://juejin.cn/post/7396118693757927450