前端显示LaTeX公式

Time:2021-06-27

前言

近来在学习神经网络,不少笔记中都使用了LaTeX进行公式的书写,考虑到准备把这些笔记也放到网站上方便日后来看,于是就整起了引入显示LaTeX公式的方法。

我的前端环境:VueCLI4.5

选择使用的是MathJax.js。

MathJax.js中文文档如下:

MathJax 中文文档 — MathJax Chinese Doc 2.0 documentation (mathjax-chinese-doc.readthedocs.io)

Author:雾雨霜星
欢迎来我的个人网站进行学习:
https://www.shuangxing.top/#/passage?id=29
转载请注明出处!

MathJax使用原理

在工程引入MathJax.js后(具体引入方法见后文),调用如下方法实现LaTeX公式的渲染:

  • MathJax.Hub.Queue:通过传入需要渲染的部分id,来实现相应内容识别LaTex公式并渲染显示。

    使用方法参考:

    const MathQueue = function (elementId) {
        if (!window.MathJax) {
            return;
        }
        window.MathJax.Hub.Queue(["Typeset", window.MathJax.Hub, document.getElementById(elementId)]);
    };
    

    此处是把MathJax.Hub.Queue进行了封装。

    其中需要我们进行提供的变量(或者相应修改写死)只有elementId。其余部分可以保持原封不动。

  • MathJax.Hub.Config:对MathJax进行渲染的详细配置,包括识别LaTex的符号、显示模式与字体、控制台输出信息等。

    一般的使用方法参考下文即可。

MathJax的引入与使用

建议使用外部引入,因为如果整个工程加入会导致打包所得文件进一步变大。

在index.html页面,外联引入MathJax.js:

<script type="text/javascript" async
        src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML">
</script>

目前我看到不少教程的思路是:在index.html使用外联引入,然后另外写一个MathJax的配置文件,这个配置文件里面封装MathJax.Hub.Config作为MathJax的初始化,封装MathJax.Hub.Queue用于输入ID调用渲染内容。在main.js引入该配置文件,设置Vue调用全局变量,从而在别的组件,通过this.commonsVariable来调用MathJax的配置文件中的函数,使用相应MathJax的渲染方法。

可惜或许是我比较菜,按照这样的思路,即使是作出了那是在做highlight.js的引入时所作的尝试修改,也没能成功。终究不是页面报错就是没有效果。

于是我就想,直接在显示文章的页面调用封装了MathJax各种使用方法的配置文件,从而直接在组件中使用里面的方法。

首先是MathJax的配置文件:

//我写在了components/MathJax/globalVariable中,开了一个文件夹MathJax,里面创建了一个js。
let isMathjaxConfig = false;//用于标识是否配置
const initMathjaxConfig = () => {
    if (!window.MathJax) {
        return;
    }
    window.MathJax.Hub.Config({
        showProcessingMessages: false, //关闭js加载过程信息
        messageStyle: "none", //不显示信息
        jax: ["input/TeX", "output/HTML-CSS"],
        tex2jax: {
            inlineMath: [["$", "$"], ["\\(", "\\)"]], //行内公式选择符
            displayMath: [["$$", "$$"], ["\\[", "\\]"]], //段内公式选择符
            skipTags: ["script", "noscript", "style", "textarea", "pre", "code", "a"] //避开某些标签
        },
        "HTML-CSS": {
            availableFonts: ["STIX", "TeX"], //可选字体
            showMathMenu: false //关闭右击菜单显示
        }
    });
    isMathjaxConfig = true; //配置完成,改为true
};
const MathQueue = function (elementId) {
    if (!window.MathJax) {
        return;
    }
    window.MathJax.Hub.Queue(["Typeset", window.MathJax.Hub, document.getElementById(elementId)]);
};
export default {
    isMathjaxConfig,
    initMathjaxConfig,
    MathQueue
}

这段代码在CSDN随处可见,不过按照发布时间的推算,大概是这个博主写的:https://www.cnblogs.com/geyouneihan/p/9743302.html
然后在我的文章显示页面组件中进行调用:

import globalVariable from '@/components/MathJax/globalVariable'
... ...
created() {
  this.GetPassage();
  if(globalVariable.isMathjaxConfig){globalVariable.initMathjaxConfig();}
  globalVariable.MathQueue("passage-main-area");
  },
}

其中this.GetPassage();是调取文件内容显示出来,我是在文章显示后再调用MathJax的方法对相应LaTeX公式进行识别并渲染。

这样对段落公式($ 开 头 的 公 式 ) 有 效 果 的 , 不 过 问 题 是 , 内 联 公 式 ( 开头的公式)有效果的,不过问题是,内联公式( )(开头的公式)没有效果,而且菜单那些设置也没有效果。

参考到MathJax中文文档,可以考虑直接通过script标签引入内联配置。

使用内联设置,在index.html配置如下:

<!-- 引入数学公式美化插件MathJax -->
  <script type="text/javascript" async
          src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML">
  </script>
  <script type="text/javascript"
          src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML,http://myserver.com/MathJax/config/local/local.js">
  </script>
  <script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    showProcessingMessages: false, //关闭js加载过程信息
    messageStyle: "none", //不显示信息
    showMathMenu: false, //关闭右击菜单显示
    availableFonts: ["STIX", "TeX"], //可选字体
    jax: ["input/TeX", "output/HTML-CSS"],
    tex2jax: {
      inlineMath: [ ['$','$'], ["\\(","\\)"] ],
      displayMath: [ ['$$','$$'], ["\\[","\\]"] ]
    }
  });
  </script>

此时所有的效果都可以达成了。

经过测试,使用内联配置下,原本MathJax中封装的配置可以删去,即原本的initMathjaxConfig变成:

const initMathjaxConfig = () => {
    if (!window.MathJax) {
        return;
    }
    isMathjaxConfig = true; //配置完成,改为true
};

同样可以达到效果。

存在缺陷

  1. 加载速度受到网络影响:

    在网速比较慢的时候,有时候页面文章显示完了,但是公式也还是没能加载出来,或者需要等很久。一般是需要重新刷新,页面才能重新把LaTeX公式渲染出来,否则看着就只是一堆符号。

  2. 控制台的报错:

    由于在index.html中引入了如下:

      <script type="text/javascript"
              src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML,http://myserver.com/MathJax/config/local/local.js">
      </script>
    

    控制台报错为:

    Failed to load resource: net::ERR_NAME_NOT_RESOLVED   myserver.com/MathJax/config/local/local.js?V=2.7.5:1
    

    点开进去myserver.com/MathJax/config/local/local.js?V=2.7.5:1,无法访问该页面。

    但是删去了我的公式就经常很久加载不出来,需要我手动刷新页面才加载出来,也不知怎么回事,所以我还是留着了。

小插曲

一开始按照别人的思路去引入MathJax并使用:

首先把别人的MathJax配置文件粘到了自己的工程目录下。

然后在main.js引入那个MathJax的配置文件:

//在 main.js 中引入MathJax的调用封装配置文件
import globalVariable from './components/Math/globalVariable'
Vue.prototype.commonsVariable = globalVariable;

但是在我以前搭建网站时就已经明白,在VueCLI4.5的工程里面,直接使用Vue对象恐怕不是那么明智,于是我尝试了进行如下的修改:

import globalVariable from '@/components/MathJax/globalVariable'
// 加入MathJax配置的Js及其调用方法
app.prototype.commonsVariable = globalVariable

然而可惜的是,没有效果。在相应我的文章显示页面调用如下:

if(this.commonsVariable.isMathjaxConfig){
                        this.commonsVariable.initMathjaxConfig();
                    }
                    this.commonsVariable.MathQueue("passage");

结果这个页面直接就报错了。

后来在main.js改为:

import globalVariable from '@/components/MathJax/globalVariable'
// 加入MathJax配置的Js及其调用方法
app.use(globalVariable)

结局依旧没有改变。。。

所以这或许是我学艺不精所致,看来对vue及其main.js中各种api的使用还需要更多的修炼啊!

来来来,看看你的网速:
U k = I k ∗ R k U_k = I_k * R_k Uk=IkRk
如果看得到下划线符号,说明LaTeX公式没有被渲染出来!网速不行啊!dddd(懂的都懂!)

Author:雾雨霜星
欢迎来我的个人网站进行学习:
https://www.shuangxing.top/#/passage?id=29
转载请注明出处!

Thanks!

PS: 毕竟,霜星酱水平有限,如果发现任何错误还请及时邮箱告知我,我会去改哦!

Logo

前往低代码交流专区

更多推荐