关于在后台编辑复杂公式并在app上展示的解决方案

132 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情

写在前面的话

新的需求:需要在后台管理系统编辑复杂公式,并存储至数据库后,在ios和安卓app进行展示。

首先想到的解决方案是让用户输入公式后转化为LaTex格式的文本存入数据库,app那边再响应展示出来即可。但经与ios和安卓反复讨论,他们不愿意用此方式,表示这样做比较麻烦。于是我只能默默把管理员输入的公式转化为图片,再传给后台存入数据库,这样app端只需要展示图片即可。

公式编辑器

网上有很多现成的编辑器demo,因本项目的编辑器只需要用到公式,所以找了下图这个编辑器

image.png

源码地址如下:

mathEditor(数学公式编辑器)

简单使用如下:

  • 由于该项目是基于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:

    源码地址:github.com/niklasvh/ht…

    html2canvas 是一个 HTML 渲染器,允许开发者在用户浏览器截取页面或部分网页的“屏幕截屏”,屏幕截图是基于 DOM。

    引用

    npm install html2canvas
    
    import html2canvas from 'html2canvas'
    

    使用

image.png

关于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("添加公式失败!")
      }

总结

自此,则成功完成了将公式转为图片存进数据库的功能。虽然这种方式并不是最优的,但基于各方沟通,只能寻求属于自己公司项目的最优解啦。