MathJaxのLaTeXから画像ファイルを錬成する
この記事はアドカレに参加しています。
LaTeXってなに?
平方根や、行列式などを綺麗に表示したいときがあります。そんなときに役に立つのが、LaTeXという記法です。例えば、Qiitaで$a = \sqrt{10}$と表示するには以下のように書きます。
a = \sqrt{10}
LaTeXで表わせる数式記号はたくさんあります。
・Qiitaでの様々な数式の書き方 ~ TeX記法を使ったサンプルコード付き
・よく忘れるので数学のTeX記法をまとめ
・場合分けをきれいに書く
・27.7 数式の書き方(1)
MathJax
web上のLaTeXで書かれたコードを実際の数式に変換してくれるライブラリにMathJaxがあります。MathJaxはQiitaでも採用されていて、Qiitaの多くの記事ではMathJaxによって数式が描かれています。
LaTeXから任意の画像ファイルへ
LaTeXから画像ファイルを作成するには、
LaTeX→SVG→DataURL(svg)→Image→canvas→DataURL(任意の画像形式)
のようにする必要があります。
1. LaTeXからSVG
MathJaxのMathJax.tex2svgPromise
を用いることで、LaTeXコードからsvg要素を作成することができます。
let str = "\\frac{1}{2}"
MathJax.tex2svgPromise(str, {display: true}).then((obj) => {
let svg_ele = obj.childNodes[0]
})
obj
はsvg文字列ではなく、nodeであることに注意する必要があります。obj.childNodes[0]
にsvg
要素が、obj.childNodes[1]
の方にはMathML
要素があります。
2. SVGをURL化
svg要素をXMLSerializer().serializeToString
でXML形式の文字列にします。さらに、その文字列からDataURLを作成します。encodeURIComponent
関数で文字列をエスケープする必要があります。
let svg = new XMLSerializer().serializeToString(obj.childNodes[0])
let svg_url = "data:image/svg+xml;charset=utf-8;," + encodeURIComponent(svg)
DataURLはdata:(MIMEタイプ);(文字コード);,(データ)
のようにします。
3. URLからcanvasに描画
Image()
コンストラクタでDataURLを読み込み、canvas要素にsvgを描画します。
let cvs = document.createElement("canvas")
let img = new Image()
img.src = svg_url
img.onload = () => {
cvs.width = img.width
cvs.height = img.height
cvs.getContext("2d").drawImage(img, 0, 0)
let url = cvs.toDataURL("image/png")
}
canvasのtoDataURL
メソッドでcanvasの内容を画像データを表すDataURLに変換することができます。ユーザーがこのDataURLを踏むことで、画像ファイルをダウンロードすることができます。
toDataURL
の引数ではMIMEタイプで画像形式を指定しますが、ブラウザが必ずしも指定した画像形式のエンコードに対応している訳ではありません。もしもブラウザがエンコードをサポートしていないMIMEタイプであった場合は、戻り値のDataURLがpng形式になります。(戻り値の最初がdata:image/png
で始まっていれば、引数で指定されたMIMEタイプをブラウザはサポートしていません。)
4. URLから自動ダウンロード処理
URLからファイルを自動ダウンロードするような処理を書くには、aタグを使用します。download
プロパティにファイル名、href
プロパティにファイル先を示すURLがある状態でaタグがクリックされると、ファイルがダウンロードされます。
let ele = document.createElement("a")
ele.download = "filename.png"
ele.href = url
ele.click()
プログラム例
download
をクリックすると、指定されたファイル名でファイルをダウンロードします。
<span>file output: </span>
<input type="text" value="sample.png" placeholder="filename.filetype" spellcheck="false" id="text"/>
<input type="button" value="download" id="button" />
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>
<script>
let str = "\\frac{1}{2}"
let text = document.getElementById("text")
let button = document.getElementById("button")
button.addEventListener("click", () => {
let ele = document.createElement("a")
ele.download = text.value
let type = ele.download.replace(/[^\.]*\.(.*)/gu, "$1")
if (type === "txt") {
ele.href = "data:text/plain;charset=utf-8;," + encodeURIComponent(str)
ele.click()
}
else {
MathJax.tex2svgPromise(str, {display: true}).then((obj) => {
let svg = new XMLSerializer().serializeToString(obj.childNodes[0])
let svg_url = "data:image/svg+xml;charset=utf-8;," + encodeURIComponent(svg)
if(type === "svg") {
ele.href = svg_url
ele.click()
}
else {
let cvs = document.createElement("canvas")
let img = new Image()
img.src = svg_url
img.onload = () => {
cvs.width = img.width
cvs.height = img.height
cvs.getContext("2d").drawImage(img, 0, 0)
ele.href = cvs.toDataURL("image/" + type)
ele.click()
}
}
})
}
})
</script>
参考文献
・MathJaxでLaTeXをsvgに変換する
・JavaScriptで動的に作成したテキストファイルをダウンロード
・SVG イメージを JavaScript から保存する方法
・[HTML/js] SVGファイルをPNGに変換するツール
・Rendering MathJax output on
むすび
LaTeXコードからファイルを錬成する話でした。