You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript如何在textarea的keyup事件中调用函数实现MathJax转PNG展示

问题原因

你的代码存在3个核心问题,导致keyup事件无法实时输出PNG:

  • MathJax全局配置被放在了每次keyup触发的myFunction函数中,MathJax仅会在首次加载时读取配置,重复覆写window.MathJax不会生效,也无法重复触发初始化逻辑
  • 每次转换后直接追加图片到容器,没有清空上一次生成的旧内容
  • 没有处理MathJax未加载完成就触发转换的异常场景,也没有防抖逻辑,输入过快会产生大量冗余转换任务

修正后代码

JS代码

// 全局存储转换方法和MathJax加载状态
let mj2img = null;
let mathJaxLoaded = false;
// 防抖定时器
let debounceTimer = null;

window.MathJax = {
  jax: ["input/TeX", "output/SVG"],
  extensions: ["tex2jax.js", "MathMenu.js", "MathZoom.js"],
  showMathMenu: false,
  showProcessingMessages: false,
  messageStyle: "none",
  SVG: {
    useGlobalCache: false
  },
  TeX: {
    extensions: ["AMSmath.js", "AMSsymbols.js", "autoload-all.js"]
  },
  AuthorInit: function() {
    MathJax.Hub.Register.StartupHook("End", function() {
      // 初始化转换方法
      mj2img = function(texstring, callback) {
        var input = texstring;
        var wrapper = document.createElement("div");
        wrapper.innerHTML = input;
        var output = { svg: "", img: ""};
        MathJax.Hub.Queue(["Typeset", MathJax.Hub, wrapper]);
        MathJax.Hub.Queue(function() {
          var mjOut = wrapper.getElementsByTagName("svg")[0];
          if(!mjOut) return callback(output);
          mjOut.setAttribute("xmlns", "http://www.w3.org/2000/svg");
          output.svg = mjOut.outerHTML;
          var image = new Image();
          image.src = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(output.svg)));
          image.onload = function() {
            var canvas = document.createElement('canvas');
            canvas.width = image.width;
            canvas.height = image.height;
            var context = canvas.getContext('2d');
            context.drawImage(image, 0, 0);
            output.img = canvas.toDataURL('image/png');
            callback(output);
          };
        });
      }
      mathJaxLoaded = true;
    });
  }
};

// 加载MathJax资源
(function(d, script) {
  script = d.createElement('script');
  script.type = 'text/javascript';
  script.async = true;
  script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js';
  d.getElementsByTagName('head')[0].appendChild(script);
}(document));

// 输入触发的转换函数
function myFunction(eqn){
  // MathJax未加载完成时不执行
  if(!mathJaxLoaded || !mj2img) return;
  // 清空上一次的防抖定时器
  clearTimeout(debounceTimer);
  // 300ms防抖,输入停止后再执行转换
  debounceTimer = setTimeout(() => {
    const target = document.getElementById("target");
    // 清空上一次的转换结果
    target.innerHTML = '';
    if(!eqn.trim()) return;
    mj2img(eqn, function(output){
      if(output.img) {
        const i = document.createElement('img'); 
        i.src = output.img; 
        target.append(i);
      }
    });
  }, 300)
}

HTML代码

<textarea onkeyup="myFunction(this.value)" placeholder="输入LaTeX公式"></textarea>
<div id="target"></div>

逻辑说明

  • MathJax的全局配置和初始化仅执行一次,启动完成后会暴露全局可用的转换方法
  • 给keyup事件增加了300ms防抖逻辑,输入停止后才触发转换,大幅减少不必要的性能消耗
  • 每次转换前先清空target容器的旧内容,页面仅会保留最新的公式转换结果
  • 增加了MathJax加载状态判断,加载完成前触发的输入事件会被忽略,避免控制台报错

内容的提问来源于stack exchange,提问作者J C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 07:36:04