搜索

首页  >  问答  >  正文

简化数学符号输入,让你在网络上更轻松

有没有一个React库的解决方案,让用户可以轻松输入数学符号,并在后端将其转换为LaTeX?我的意思是,像一个用户友好的编辑器,可能带有可点击的按钮?然后在后端将这些元素转换为LaTeX。

P粉057869348P粉057869348442 天前601

全部回复(1)我来回复

  • P粉637866931

    P粉6378669312023-09-15 11:44:19

    您可以尝试使用MathJax。版本3是最新版本,非常强大。

    根据这个问题,它是最好的JavaScript LaTeX渲染器。

    在下面的示例中,您可以将现有内容渲染为LaTeX,或者动态添加元素。

    const expressions = [
      '\frac{a}{b}',
      '\(V = {4 \over 3} \pi^3 \)'
    ];
    
    document.querySelectorAll('.expression').forEach(el => {
      el.replaceWith(MathJax.tex2chtml(el.textContent));
    });
    
    expressions.forEach(expression => {
      document.body.append(MathJax.tex2chtml(expression));
    });
    html, body {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    body {
      display: flex;
      justify-content: space-around;
      align-items: center;
    }
    
    body > * {
      border: thin solid grey;
      padding: 1rem;
    }
    <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
    <div class="expression">(\int_{a}^{b} x^2 \,dx)</div>

    将中缀表达式解析为LaTeX

    如果您想解释表达式并将其转换为LaTeX,可以尝试以下内容:

    const form = document.forms['latex-add'];
    const container = document.querySelector('#expression-list');
    const expressions = ['\frac{a}{b}', '\frac{{(25 \cdot 5)}}{6}'];
    
    const main = () => {
      form.elements.expression.value = '(25*5)/b';
      form.addEventListener('submit', handleAdd);
      renderExpressions();
    };
    
    const handleAdd = (e) => {
      e.preventDefault();
      const expression = e.target.elements.expression.value.trim();
      const tex = texFromExpression(expression);
      console.log(tex);
      expressions.push(tex);
      renderExpressions();
      e.target.reset();
    };
    
    const renderExpressions = () => {
      container.innerHTML = '';
      expressions.forEach(expression => {
        const wrapper = document.createElement('div');
        wrapper.classList.add('expression');
        const tex = document.createElement('div');
        tex.classList.add('tex');
        tex.textContent = expression;
        wrapper.append(tex);
        wrapper.append(MathJax.tex2chtml(expression));
        container.append(wrapper);
      });
    };
    
    // Credit: https://stackoverflow.com/a/57449164/1762224
    const texFromExpression = (str) => {
      let pos = -1, ch;
    
      const nextChar = () => {
        ch = (++pos < str.length) ? str.charAt(pos) : -1;
      };
    
      const eat = (charToEat) => {
        while (ch == ' ') nextChar();
        if (ch == charToEat) {
          nextChar();
          return true;
        }
        return false;
      };
    
      const parse = () => {
        nextChar();
        const x = parseExpression();
        if (pos < str.length) throw new Error(`Unexpected: ${ch}`)
        return x;
      };
    
      const parseExpression = () => {
        let x = parseTerm();
        while (true) {
          if (eat('+')) x = `${x} + ${parseTerm()}` // addition
          else if (eat('-')) x = `${x} - ${parseTerm()}` // subtraction
          else return x;
        }
      };
    
      const parseTerm = () => {
        var x = parseFactor();
        while (true) {
          if (eat('*')) x = `${x} \cdot ${parseTerm()}`; // multiplication
          else if (eat('/')) x = `\frac{${x}}{${parseTerm()}}`; // division
          else return x;
        }
      };
    
      const parseFactor = () => {
        if (eat('+')) return parseFactor(); // unary plus
        if (eat('-')) return `-${parseFactor()}`; // unary minus
        let x;
        const startPos = pos;
        if (eat('(')) { // parentheses
          x = `{(${parseExpression()})}`
          eat(')');
        } else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
          while ((ch >= '0' && ch <= '9') || ch == '.') nextChar();
          x = str.substring(startPos, pos);
        } else if (ch >= 'a' && ch <= 'z') { // variables
          while (ch >= 'a' && ch <= 'z') nextChar();
          x = str.substring(startPos, pos);
          if (x.length > 1) {
            x = `\${x} {${parseFactor()}}`;
          }
        } else {
          throw new Error(`Unexpected: ${ch}`);
        }
        if (eat('^')) x = `${x} ^ {${parseFactor()}}` // superscript
        if (eat('_')) x = `${x}_{${parseFactor()}}`;
        return x;
      }
      return parse();
    }
    
    main();
    #expression-list {
      display: flex;
      flex-direction: row;
      justify-content: center;
      align-items: center;
      gap: 0.5rem;
    }
    
    .expression {
      padding: 0.5rem;
      border: thin solid grey;
    }
    
    .tex {
      font-family: monospace;
      font-size: smaller;
    }
    <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
    <form name="latex-add" autocomplete="off">
      <label for="expression">Expression:</label>
      <input type="text" id="expression" name="expression"
             value="" placeholder="Expression..." />
      <button type="submit">Add</button>
    </form>
    <hr />
    <div id="expression-list"></div>

    回复
    0
  • 取消回复