1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 【笔记】微信公众号插入数学公式(矢量图格式)的若干尝试

【笔记】微信公众号插入数学公式(矢量图格式)的若干尝试

时间:2023-09-06 02:58:32

相关推荐

【笔记】微信公众号插入数学公式(矢量图格式)的若干尝试

微信公众号文章中可插入的富文本格式不如一般的博客自由,但目前来说也是中文互联网勉强都能接受的一个平台和事实标准了。然而,在撰写理工相关的文章时不免要用到数学公式,微信公众号不支持数学公式的插入和编辑,用图片(位图)代替又比较麻烦,截图、上传,尤其是行间公式排版相当麻烦。

目前来说,最佳的方案是将公式转换为 SVG 图片格式插入。SVG 是矢量图格式,在不同设备上都能清晰显示,而且可以以 DOM 的形式嵌入到富文本中,还有简单而严格安全的交互功能。

但是就目前可查阅到的资料来看,实现这一功能的仅有 ciaochaos 实现的微信公众号公式编辑插件和部分功能收费的 MdNice。笔者在这近一个月的时间里,结合这两年对数学公式排版的研究经验,对功能实现的一些技术难点一一突破,下面简记之,供自己参考。

分析 tex-svg-full.js

MpMath 插件的核心模块是引用的 MathJax 的tex-svg-full.js文件,这个文件提供了所有数学符号对应的 SVG 数据,均是以 path 绘制的,如

8715:"96 251Q96 268 119 281H363Q607 281 607 283Q607 295 600 319T576 379T519 451T425 507Q386 521 361 523T233 526L119 527Q96 535 96 557Q96 578 116 585Q121 587 229 587Q238 587 257 587T288 588Q366 588 435 568T568 488Q670 388 670 251Q670 155 621 78T499 -39T345 -85Q336 -86 225 -86L119 -85Q96 -77 96 -55Q96 -38 119 -25H233Q356 -24 371 -21Q373 -21 393 -16Q468 3 523 55T599 177Q607 206 607 218Q607 220 363 220L119 221Q96 229 96 251"

MathJax 的大版本互相不兼容,主要的版本是 MathJax 2.x、3.x 以及最新的 4.x,4.x 不再在原有的 Repository 基础上修改,而是另起炉灶为MathJax-srcRepository。

所以在分析时要分清版本。MathJax 3.x 版本路径如下

/mathjax/MathJax/blob/develop/es5/tex-svg-full.js

该文件应该是由output/svg/fonts/文件打包而成的。如下tex.js文件中就包含了大部分数学符号的 SVG 数据。

/mathjax/MathJax/blob/master/es5/output/svg/fonts/tex.js

ciaochaos 的插件中用的tex-svg-full.js如下

/ciaochaos/mpMath/master/mpMath/assets/js/tex-svg-full.js

文件体积还略大于官方的版本,暂不清楚原因。

更多版本的tex-svg-full.js如下

/mathjax/file/tex-svg-full.js/?id=53958#

MathJax 2.x 是没有tex-svg-full.js的,而是分成各个字体,各字体又分AMSVariant这些目录,目录中的javascript文件中定义一部分符号的 SVG 数据。

/hemashushu/mathjax-compact/blob/master/jax/output/SVG/fonts/STIX-Web/Alphabets/Bold/Main.js

但不知道为什么,MathJax 3.0 版本开始后,就不再提供其它数学字体了(包括 STIX 字体),至少在 Repository 中看不到了。因此下面的链接是不存在的。

/mathjax/MathJax/tree/master/fonts/HTML-CSS

需要切换 branch 到 MathJax 2.x 的版本,如下

/mathjax/MathJax/tree/woff2/jax/output/SVG/fonts/STIX-Web

/mathjax/MathJax/tree/v2.6-latest/fonts/HTML-CSS/STIX-Web

需要注意的是,MathJax 2/3 在对数学符号编码时可能有不同之处,可能有的 dict key 用的是十进制数字,有的是十六进制数字,无法直接对应。

GitHub 还有对 MathJax 2.x 的散碎文件整体合并的版本:

/hemashushu/mathjax-compact/tree/master/jax/output/SVG/fonts/STIX-Web

/pkra/MathJax-single-file/blob/master/dist/TeXSVGSTIX-Web/MathJax.js

MdNice 的实现

MdNice 将 Markdown 转换为适合微信公众号排版的样式,数学公式用的是 MathJax。最后将渲染的 DOM 复制粘贴到微信公众号。

粘贴到公众号

复制时格式必须为text/html,所以要借助 JavaScript 实现。

function copyToClip(str) {function listener(e) {e.clipboardData.setData("text/html", str);e.clipboardData.setData("text/plain", str);e.preventDefault();}document.addEventListener("copy", listener);document.execCommand("copy");document.removeEventListener("copy", listener);};

代码来自:Copy to clipboard pure JavaScript - JSFiddle - Code Playground,实测可用

或者引入 JavaScript 库:clipboard.js — Copy to clipboard without Flash ()

除了 Web 端,在桌面应用多次测试,Python 是无法实现这样的功能的,至少用win32clipboard模块是无法实现的(CF_TEXTCF_UNICODETEXTBytesStr等多种数据类型和剪贴板类型均无效)。

MathJax 渲染为 SVG

MathJax 目前在国内外是事实上的前端数学公式排版标准,但是 MathJax 还是比较重,加载较慢;相对的 KaTeX 的渲染方法更加传统,速度更快。然而 KaTeX 到目前也不支持 SVG 渲染,所以可选的只有 MathJax,将 MathJax 的 LaTeX 数学公式渲染为 SVG。

但是,MathJax 渲染的结果通常使用 cache 技术,用<use>标签的引用调用数学字符的数据 path 加快页面显示效率。然而,这样的结果复制到公众号是无法正常显示的,必须要复制完整的 path。

<svg xmlns:xlink="/1999/xlink" width="5.21ex" height="2.301ex" viewBox="0 -764.4 2243.1 990.7" role="img" focusable="false" style="vertical-align: -0.525ex;"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><use xlink:href="#STIXWEBMAINI-61" x="0" y="0"></use><use xlink:href="#STIXWEBMAIN-2260" x="779" y="0"></use><use xlink:href="#STIXWEBMAIN-30" x="1742" y="0"></use></g></svg>

相关链接参考:

https://codepen.io/pkra/pen/RwbyKM

/blog/MathJaxEditor.htm

MathJax 官方提供的测试工具

最终还是靠查询官方文档解决问题:The SVG output processor — MathJax 2.7 documentation,更改useFontCache: true配置,将其设置为false

如下 MathJax 4.x 的配置方法,以供参考(MathJax 3.x 配置参数基本相同,更低的版本可能不同,不推荐使用)

MathJax.Hub.Config({jax: ["input/MathML","output/SVG"],extensions: ["mml2jax.js","MathEvents.js"],MathML: {extensions: ["content-mathml.js"]},SVG: {mtextFontInherit: true,blacker: 1,useFontCache: false, // 禁用 cache, 输出每个字符的 path 数据useGlobalCache: false,linebreaks: {automatic: true }},menuSettings: {zoom: "Click"},MatchWebFonts: {matchFor: {SVG: true},fontCheckDelay: 500,fontCheckTimeout: 15 * 1000},messageStyle: "none"});

得到的结果:

<svg xmlns:xlink="/1999/xlink" width="5.21ex" height="2.301ex" viewBox="0 -764.4 2243.1 990.7" role="img" focusable="false" style="vertical-align: -0.525ex;"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><path stroke-width="1" d="M463 111l13 -11c-75 -91 -99 -110 -139 -110c-28 0 -40 12 -40 41c0 25 2 33 23 115c-75 -113 -133 -157 -203 -157c-56 0 -100 40 -100 116c0 155 153 336 286 336c43 0 72 -21 80 -58l11 48l3 3l61 7l7 -3c-2 -9 -3 -11 -6 -21c-47 -171 -89 -343 -89 -363 c0 -7 6 -13 14 -13c9 0 22 8 52 41zM365 361c0 35 -21 58 -56 58c-45 0 -89 -31 -131 -92c-42 -63 -77 -152 -77 -215c0 -55 24 -74 60 -74c50 0 97 55 127 98c47 68 77 154 77 225Z"></path><g transform="translate(779,0)"><path stroke-width="1" d="M637 120h-326l-120 -276h-54l120 276h-209v66h238l59 134h-297v66h326l120 276h54l-121 -276h210v-66h-238l-59 -134h297v-66Z"></path></g><g transform="translate(1742,0)"><path stroke-width="1" d="M476 330c0 -172 -63 -344 -226 -344c-171 0 -226 186 -226 350c0 177 69 340 230 340c131 0 222 -141 222 -346zM380 325c0 208 -44 325 -132 325c-83 0 -128 -118 -128 -321s44 -317 130 -317c85 0 130 115 130 313Z"></path></g></g></svg>

进一步修改其它配置参数,可以更美观:

SVG: {scale: 95, // 公式大小设置为 95% 在与文本混排时不会显得太突兀font: "STIX-Web" // Times 风格的 STIX 字体字符丰富,风格上比较符合国内的排版标准}

参考:https://codepen.io/mowchann/pen/xxPEqgO

最终效果

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。