持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情
写在前面的话
新的需求:需要在后台管理系统编辑复杂公式,并存储至数据库后,在ios和安卓app进行展示。
首先想到的解决方案是让用户输入公式后转化为LaTex格式的文本存入数据库,app那边再响应展示出来即可。但经与ios和安卓反复讨论,他们不愿意用此方式,表示这样做比较麻烦。于是我只能默默把管理员输入的公式转化为图片,再传给后台存入数据库,这样app端只需要展示图片即可。
公式编辑器
网上有很多现成的编辑器demo,因本项目的编辑器只需要用到公式,所以找了下图这个编辑器
源码地址如下:
简单使用如下:
-
由于该项目是基于jquery的,那么需要引入jquery和该编辑器
<script src="./jquery.js"></script> <script src="./mathEdit.min.js"></script>
-
使用
<div id="myEdits"></div> <button id="getVal">获取值</button> <script> var mathEdit = new window.MathEdit({ elId: 'myEdits', config: { defaultFontSize: '18px', viewFontSize: '14px' } }) document.getElementById('getVal').addEventListener('click',function(){ console.log(mathEdit.getValue()) //获取到的 }) </script>其中:defaultFontSize表示输入时显示的字体大小,viewFontSize表示输出的html显示的字体大小
有API可供使用:getValue表示获取用户输入值(返回html),getLatex表示获取用户输入的公式的LaTex格式数据,isEmpty判断输入框是否为空
至此,公式编辑器则开发完成
将公式转化为图片
如何将公式转化为图片呢?把编辑器截图转为图片肯定是不可靠的,那么我就采用MathJax.getLatex获取到值,再使用MathJax插件将LaTex格式的数据转化为公式放入一个div中,这样就可以将这个div截图转为图片了。
-
首先使用MathJax插件将LaTex格式的数据转化为公式
引入MathJax
<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>使用
const test = document.createElement("span"); test.id = "jme-math-content"; test.innerHTML = "$" + this.mathEdit.getLatex() + "$"; const d: any = document.getElementById("head"); d.appendChild(test); this.$nextTick(() => { const { MathJax = "" }: any = window; if (!MathJax) { return; } MathJax.Hub.Config({ tex2jax: { inlineMath: [["$", "$"]] }, messageStyle: "none" }); MathJax.Hub.Queue([ "Typeset", MathJax.Hub, document.getElementById("jme-math-content") ]); }); -
最后使用html2canvas插件将公式块转为图片,再将其上传给后台
关于html2canvas:
html2canvas 是一个 HTML 渲染器,允许开发者在用户浏览器截取页面或部分网页的“屏幕截屏”,屏幕截图是基于 DOM。
引用
npm install html2canvasimport html2canvas from 'html2canvas'使用
关于html2canvas 所有可用的配置项可查阅allenchinese.github.io/html2canvas…
具体业务代码:
const dom: any = document.getElementById("jme-math-content");
const box: any = window.getComputedStyle(dom);
const width = parseInt(box.width, 10);
const height = parseInt(box.height, 10);
const scaleBy = 1;
const canvas: any = document.createElement("canvas");
canvas.width = width * scaleBy;
canvas.height = height * scaleBy;
canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;
// 获取画笔
const context = canvas.getContext("2d");
context.scale(scaleBy, scaleBy);
await html2canvas(dom, {
canvas,
allowTaint: false,
useCORS: true
});
//业务代码:将图片上传至服务器
const res: any = await fileDataFn(canvas, 0, "image/jpeg");
const file = res.file;
const fileExt = "jpg";
const { code = "000", data = {} } =
(await uploadFileOfOSS({ file, datas: { fileExt } })) || {};
if (code == "999") {
this.$message.error("添加公式成功!")
} else {
this.$message.error("添加公式失败!")
}
总结
自此,则成功完成了将公式转为图片存进数据库的功能。虽然这种方式并不是最优的,但基于各方沟通,只能寻求属于自己公司项目的最优解啦。