schedule2020-01-09

NuxtjsとMathJaxで数式エディタをつくってみる

NuxtjsとMathJaxで数式エディタの簡単なサンプルを作成しました。

Nuxt+Mathjaxで数式の変換のデモ

MathJaxについて

MathJaxはすべてのブラウザで動作する数学用のJavaScript描画エンジンです。

MathJax.jsをCDNで読み込むとHTML内の文章からTeX形式の文を変換します。

<h4>The Lorenz Equations</h4>
<p>
\begin{align}
\dot{x} &amp; = \sigma(y-x) \\
\dot{y} &amp; = \rho x - y - xz \\
\dot{z} &amp; = -\beta z + xy
\end{align}
</p>

<h4>A Cross Product Formula</h4>
<p>\[
    \mathbf{V}_1 \times \mathbf{V}_2 =
    \begin{vmatrix}
    \mathbf{i} &amp; \mathbf{j} &amp; \mathbf{k} \\
    \frac{\partial X}{\partial u} &amp; \frac{\partial Y}{\partial u} &amp; 0 \\
    \frac{\partial X}{\partial v} &amp; \frac{\partial Y}{\partial v} &amp; 0 \\
    \end{vmatrix}
\]</p>

こんな感じのHTMLを書いておき、MathJax.jsを読み込むと下のように数式に変換してくれます。

数式右クリックするとメニューが開きTeXを確認できる。

今回のようにエディタとして使う場合は、入力からTeXを変換して描画する必要があります。 Vueでエディタを作るサンプルは見つかるのですが、自分の環境で実行できなかった。 幾つか試してnpmのvue-mathjaxを使う方法でできました。

MathJaxをCDNから利用する

NuxtにMathJaxを導入します。

このブログに専用のページを作ってそこで動作するようにしました。npmで導入する方法が分からなかったのでCDNから導入します。クエリパラメータのconfig=TeX-AMS-MML_SVGは出力を指定しています。この例ではSVGに変換します。

export default {
  head() {
    return {
      script: [
        {
          src: "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-AMS-MML_SVG"
        }
      ],
    };
  },

また、コンフィグを設定する場合はcreated()の中で設定する。 MathJax.Hub.Config({..});と設定しようとMathJax is not definedが出るため、if (process.browser) {}の中で宣言すると可能。(参考:【Nuxt.js】ReferenceError: window is not defined ってエラーが出た

export default {
  ...,
  created() {
    if (process.browser) {
      window.MathJax.Hub.Config({
        // MathJaxの設定
        extensions: ["tex2jax.js"],
        jax: ["input/TeX", "output/HTML-CSS"],
        tex2jax: {
        inlineMath: [ ['$','$'], ["\\(","\\)"] ],
        displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
        processEscapes: true
        },
        "HTML-CSS": { fonts: ["TeX"] }
      });
    }
  },

これでHTML内のTeXを変換してくれます。

TeXエディタを作る

まず、npmのvue-mathjaxをインストールする。 これを使うと数式をリアルタイムで編集できます。

npmのデモの様子。 demo

# install
$ npm install --save vue-mathjax

単体では動かず、Mathjax.jsのインストールも忘れないように。今回はCDNを上述のように取り込んでます。

作成したエディタのコードを載せます。 CSSフレームワークとしてBulmaを利用している。

<template>
    <article class="section body">
      <div class="field is-horizontal">
        <div class="field-label">
          <label class="label">LaTeXを入力</label>
        </div>
        <div class="field-body">
          <div class="field">
            <div class="control">
                <!-- TeXの入力フォーム -->
              <textarea
                class="textarea"
                v-model="formula"
                placeholder="e.g. $$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$"
              ></textarea>
            </div>
            <p class="help">
              TeX形式は
              <code>$...$</code> または
              <code>$$...$$</code> と区切り文字で囲って下さい。
              (さらに
              <code>\(...\)</code><code>\[...\]</code>も対応しています )
            </p>
          </div>
        </div>
      </div>
    </article>

    <article class="section body">
      <div class="field is-horizontal">
        <div class="field-label">
          <label class="label">変換結果</label>
        </div>
        <div class="field-body">
          <div class="field is-narrow">
            <div class="control">
                <!-- 数式の出力先 -->
              <vue-mathjax :formula="formula"></vue-mathjax>
            </div>
          </div>
        </div>
      </div>
    </article>
</template>
<script>
import { VueMathjax } from "vue-mathjax";

export default {
  components: {
    "vue-mathjax": VueMathjax
  },
  head() {
    return {
      script: [
        {
          src:
            "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-AMS-MML_SVG"
        }
      ]
    };
  },
  created() {
    MathJax;
    if (process.browser) {
      window.MathJax.Hub.Config({
        // MathJaxの設定
        extensions: ["tex2jax.js"],
        jax: ["input/TeX", "output/HTML-CSS"],
        tex2jax: {
        inlineMath: [ ['$','$'], ["\\(","\\)"] ],
        displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
        processEscapes: true
        },
        "HTML-CSS": { fonts: ["TeX"] }
      });
    }
  },
  data() {
    return {
      formula: `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}.$$
    };
  }
};
</script>

これでデモのように実行できました。

おわりに

TeX形式の数式をブラウザで表示するプラグインは、MathJaxの他にKaTeXがあります。

  • KaTeXはHTML形式で表現しており、数式のレンダリングがかなり早い特徴を持っています。
  • MathJaxはレンダリング速度ではKaTeXにかないませんが、右クリックのメニューからTeXのソースを表示やSVGで出力できると機能が豊富です。

個人的にはKaTeXが使いやすい印象ですが、今後、比較してまとめたいと考えてます。