美文网首页
vue3解析数学公式图片,页面展示并转换为Word格式

vue3解析数学公式图片,页面展示并转换为Word格式

作者: 我是七月 | 来源:发表于2023-06-11 18:02 被阅读0次

    有这样一个需求:通过数学公式图片,识别书公式展示在页面上,并支持下载word,展示word版本的数学公式,可供复制使用。
    之前是通过Pix2Text进行数学公式的识别,然后复制识别的内容,通过 LaTeX公式编辑器进行下载对应的数学公式的Word 文档。但是第一个网站Pix2Text不太稳定,经常性的不可用,所以想自己实现这2个功能。

    一、图片OCR解析公式

    首先参考第一个的Pix2Textgithub
    后端进行部署了相关的服务,可以进行OCR解析图片,然后前端进行调用对应的接口
    这块主要有一个是粘贴图片进行上传,并显示在页面上

    1、首先需要监听全局paste事件

    onMounted(() => {
      window.addEventListener('paste', handlePaste);
    });
    onUnmounted(() => {
      window.removeEventListener('paste', handlePaste);
    });
    

    2、然后再对应的监听方法中就可以获取到file文件

    /** 全局页面监听粘贴内容 */
    function handlePaste(event) {
      // console.log('全局页面监听粘贴内容000');
      const items = (event.clipboardData || window.clipboardData).items;
      let file = null;
    
      if (!items || items.length === 0) {
        console.log('当前浏览器不支持本地');
        return;
      }
      // 搜索剪切板items
      for (let i = 0; i < items.length; i++) {
        if (items[i].type.indexOf('image') !== -1) {
          file = items[i].getAsFile();
          break;
        }
      }
      if (!file) {
        console.log('粘贴内容非图片');
        return;
      }
      // 此时file就是我们的剪切板中的图片对象
      // console.log('file==', file);
      showImageToPage(file);
      uploadImage(file);
    }
    

    3、然后显示这个图片在页面上,div设置一个id

       <div id="preview" class="div_image">
                <span>将图片按Ctrl+V粘贴至此页面</span>
       </div>
    

    4、把刚才获取到的file文件渲染在div上

    // 上传的图片显示到页面右侧
    function showImageToPage(file) {
      // 如果需要预览,可以执行下面代码
      const reader = new FileReader();
      reader.onload = event => {
        preview.innerHTML = `<img src="${event.target.result}" style=' max-height: 200px;
        max-width: 100%;
        min-width: 200px;
        object-fit: contain;'>`;
      };
      // 把粘贴的图片显示在页面上
      reader.readAsDataURL(file);
    }
    

    5、然后调用后台的上传图片,OCR解析接口

    // 上传图片到服务端进行OCR识别
    function uploadImage(file) {
      let param = new FormData(); //创建form对象
      param.append('image', file); //为创建的form对象增加上传的文件
      // param.append('session_id', ''); //如果需要上传其他字段,在这里增加
      param.append('use_analyzer', 'true');
      param.append('resized_shape', '600');
      //修改请求头
      let config = { headers: { 'Content-Type': 'multipart/form-data' } };
      // console.log('url ==', pix2textUrl);
    
      proxy.$modal.loading('正在解析,请稍候!');
      // 上传图片
      axios.post(pix2textUrl, param, config).then(res => {
        // console.log('res====', res);
        proxy.$modal.closeLoading();
    
        if (!res.data || res.data.status_code != 200) {
          proxy.$modal.msgError('未成功识别,请稍后再试');
          return;
        }
        // console.log('res====', res);
    
        let textList = res.data.results;
        if (!textList || textList.length == 0) {
          proxy.$modal.msgError('未成功识别,请稍后再试');
          return;
        }
    
        let textStr = '';
        textList.forEach(element => {
          textStr += element.text;
          if (element.type == 'text') {
            textStr += '\n';
          }
        });
        // console.log('textStr====', textStr);
    
        textWords.value = textStr.replaceAll('$$', '');
        mathText.value = textStr;
    
        laTexToMath();
      });
    }
    

    二、页面展示数学公式

    接口会返回一些解析出来的文本和LaTeX 数学公式
    但是接口返回的LaTeX 公式,是一些$$符号的一些标识,具体符号参考见 LaTeX 公式篇 ,无法辨认出具体的公式,所以需要转化显示为可以识别的公式。

    所以我们需要借助于 MathJax

    mathjax是一个用于latex、mathml和ascimath表示法的开源javascript显示引擎,可在所有现代浏览器中工作,并内置了对诸如屏幕阅读器等辅助技术的支持。

    1、首先需要在 index.html中引入

      <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
    

    2、在utils中新建MathJax.js

    let isMathjaxConfig = false // ⽤于标识是否配置
    const initMathjaxConfig = () => {
        if (!window.MathJax) {
            return
        }
        window.MathJax = {
            tex: {
                inlineMath: [
                    ['$', '$'],
                    ['\\(', '\\)']
                ], // ⾏内公式选择符
                displayMath: [
                    ['$$', '$$'],
                    ['\\[', '\\]']
                ] // 段内公式选择符
            },
            chtml: {
                scale: 1,//缩放比例
            },
            options: {
                skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code',
                    'a'], // 避开某些标签
                ignoreHtmlClass: 'tex2jax_ignore',
                processHtmlClass: 'tex2jax_process'
            }
        }
        isMathjaxConfig = true // 配置完成,改为true
    }
    const TypeSet = async function (elementId) {
        if (!window.MathJax) {
            return
        }
        window.MathJax.startup.promise = window.MathJax.startup.promise
            .then(() => {
                return window.MathJax.typesetPromise()
            })
            .catch((err) => console.log('Typeset failed: ' + err.message))
        return window.MathJax.startup.promise
    }
    export default {
        isMathjaxConfig,
        initMathjaxConfig,
        TypeSet
    }
    

    3、在main.js中全局引入

    import MathJax from './utils/MathJax'
    app.config.globalProperties.MathJax = MathJax
    

    4、在刚才上传图片接口,之后调用这个接口,传入接口返回的latex文本即可

     <!-- 展示数学公式 -->
    <div class="input_box math_box" style="margin-left: 10px" id="math">
        <p style="font-size: 14px; white-space: pre-line">{{ mathText }}</p>
    </div>
    
    // 将Latex公式文本渲染为数学公式显示在右侧虚线框中
    function laTexToMath() {
      // MathJax3.0版本
      if (proxy.MathJax.isMathjaxConfig) {
        // 判断是否初始配置,若⽆则配置。
        proxy.MathJax.initMathjaxConfig();
      }
      proxy.MathJax.TypeSet();
    }
    

    效果如下图所示


    WX20230612-173535@2x.png

    三、转化下载Word格式的公式

    上面的公式已经可以完整的展示在页面上,但是我们不是通过复制粘贴出来,所以需要把这个转换为Word版本的,可以进行复制粘贴的格式。
    参考 LaTeX公式编辑器,通过这个里面的导出Word,有一个接口可以进行实现,接口地址为https://reverse.latexlive.com:5002/api/Common/MathMlToWordBlod,但是通过抓包发现这个接口的入参格式为 MathML格式,入下图所示

    MathML格式

    上面类似Html的格式,就是MathML格式,
    所以我们需要将之前接口返回的laTex转MathML格式,然后再调研下载Word的接口,
    1、laTex转MathML格式

    // 需要先把laTex转MathML格式,然后通过MathML格式进行下载Word
    function exportWord() {
      // console.log('laTex转MathML格式');
      if (!textWords.value) {
        proxy.$modal.msgError('请先粘贴图片识别');
        return;
      }
      // 重置
      window.MathJax.texReset();
      // laTex转MathML格式
      window.MathJax.tex2mmlPromise(textWords.value)
        .then(function (mml) {
          // 转换结果
          // console.log('转换结果mml=====', mml);
          downloadWordFile(mml);
        })
        .catch(function (err) {
          // 发生错误时
        })
        .then(function () {
          // 完成时
        });
    }
    

    2、下载Word文件

    / /下载Word文件-通过MathML格式进行下载Word
    function downloadWordFile(mathml) {
      // console.log('下载word文件00');
      let param = {
        mathml: mathml
      };
      const config = {
        responseType: 'blob', //这个一定要设置,否则会出现文件下载后打不开的情况,
        'Content-Type': 'application/json'
      };
      axios.post(mathMlToWordBlodUrl, param, config).then(res => {
        // console.log('res====', res);
        // console.log('下载word文件11');
        let blob = new Blob([res.data], {
          //设置数据源
          type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' //设置文件格式
        });
    
        let objectUrl = URL.createObjectURL(blob); //创建下载的链接
        let a = document.createElement('a');
        a.href = objectUrl;
    
        let time = parseInt(new Date().getTime() / 1000) + '';
        a.download = `jwwh${time}`; //设置文件名
        //下面这个写法兼容火狐
        a.dispatchEvent(
          new MouseEvent('click', { bubbles: true, cancelable: true, view: window })
        );
        window.URL.revokeObjectURL(blob); //释放bolb对象
      });
    }
    
    Word格式展示

    参考文档:
    vue中使用MathJax 3.0简单步骤
    mathjax
    基于vue渲染Latex数学公式(simplemde-editor)
    LatexToMathML
    uniapp使用mathjax解析公式

    相关文章

      网友评论

          本文标题:vue3解析数学公式图片,页面展示并转换为Word格式

          本文链接:https://www.haomeiwen.com/subject/xkooedtx.html