【问题标题】:MathJax inside SVGSVG 中的 MathJax
【发布时间】:2013-04-04 10:44:25
【问题描述】:

我正在写一些使用 MathJax 来呈现数学的文章。我偶尔也会包含由 javascript 动态生成的 SVG 图表。这些 SVG 图表偶尔会包含数学。

我希望使用 MathJax 呈现这些 SVG 图表中的文本元素。我知道如何cause the dynamic math to be rendered。但是,mathjax 输出位于 <span>s 中,它们不是有效的 SVG 并且不会显示。

当我将 MathJax 配置为使用 SVG 输出模式时,这种情况仍然存在,尽管这可能是由于 SVG 输出模式使用不当造成的。我通过 MathJax CDN 链接更改为 http://cdn.mathjax.org/mathjax/2.1-latest/MathJax.js?config=TeX-AMS-MML_SVG,它没有产生 SVG 输出。我还没有能够哄骗 MathJax 实际输出 SVG 元素。

我考虑过使用不理想的 SVG <foreignObject> 标签,因为(据我所知)我必须指定宽度和高度,这很不方便。

有没有更好的方法在 HTML 中的 SVG 中包含 MathJax 渲染的文本?

【问题讨论】:

标签: html svg mathjax


【解决方案1】:

目前,在 SVG 图表中包含 MathJax 的唯一方法是通过 <foreignObject>。是的,不理想,不仅因为需要提供大小,还因为IE9+不支持<foreignObject>

至于 SVG 输出,如果您使用 MathJax 上下文菜单来选择数学渲染,这将覆盖文档中的渲染器选择,因此您可能仍然会看到 HTML-CSS 输出。该值存储在 cookie 中,以便在会话之间记住它。您可以删除 cookie 以移除设置,或再次使用 MathJax 菜单选择 SVG 渲染。

但是请注意,这也对您没有帮助,因为 MathJax 的 SVG 输出不仅仅是可以包含到更大的 SVG 文件中的 SVG sn-p,还包含一些 HTML 和 <svg> 元素本身。此外,MathJax 需要周围的 HTML 来确定要使用的字体大小和其他一些因素,因此它不能直接放入您的 SVG 图表中。

<foreignObject> 方法确实是目前唯一可靠的方法。

编辑:这是一个完整的例子:

<!DOCTYPE html>
<html>
<head>
<title>MathJax in SVG diagram</title>
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_SVG"></script>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="500">
  <circle cx="100" cy="100" r="99" fill="yellow" stroke="red" />
  <circle cx="100" cy="100" r="3" fill="blue" />
  <foreignObject x="100" y="100" width="100" height="100">
    <div xmlns="http://www.w3.org/1999/xhtml" style="font-family:Times; font-size:15px">
    \(\displaystyle{x+1\over y-1}\)
    </div>
  </foreignObject>
</svg>
</body>
</html>

【讨论】:

  • 你能在某处有一个完整的例子吗?我已经在 IPython 笔记本中尝试过,但无法处理数学部分(尽管同一页面上的其他公式已正确处理)。 TIA!
  • @akim,我在答案中添加了一个示例。
  • 非常感谢。实际上我已经找到了这个完全相同的例子 :) 但是我不能让它在 IPython 笔记本中工作:( LaTeX ( )、$...$ 等仍然存在。实际上,如果我构建一个完整的 HTML 它就可以工作小部件,但是当我尝试生成 SVG 小部件时,它无法正常工作。有什么线索吗?
  • 其实,更具体地说,我的目标是在 IPython 中渲染一个带有 LaTeX 标签的 GraphViz 源代码,由 MathJax 渲染。我知道这有点错误,因为 dot 将使用源代码的大小而不是渲染公式的大小,但无论如何这比纯文本要好。
  • 对不起,我从来没有用过 IPython,所以我不能在那里给你任何建议。与创建 SVG 的时间相比,它可能与调用 MathJax 的时间有关(在 SVG 就位后需要调用 MathJax)。也可能是 SVG 被 tex2jax_ignore 元素保护免受 MathJax 的影响。您可能需要与 IPython 人员合作才能弄清楚。
【解决方案2】:

有一种方法可以在 SVG 图表中包含 MathJax SVG 元素,而不需要 foreignObject。 该技术的完整演示位于http://puzlet.com/m/b00b3

假设您的网页中有这样的 SVG 图(并包含任何 SVG 元素):

<svg id="diagram" xmlns='http://www.w3.org/2000/svg' 
    xmlns:xlink="http://www.w3.org/1999/xlink"
    version='1.1' width='720' height='100'>
</svg>

以及以下 MathJax:

<div id="mathjaxSource">
$\Omega$
</div>

使用此 CoffeeScript(加上 jQuery)将 MathJax 元素集成到您的 SVG 图表中:

diagram = $("#diagram")  # SVG diagram
obj = new MathJaxObject "mathjaxSource"  # MathJax object (see class definition below)
obj.appendTo diagram  # Append MathJax object to diagram
obj.translate 100, 200  # Position MathJax object within diagram

您还可以使用width()height() 方法进行居中和垂直对齐。

class MathJaxObject

    constructor: (@divId, @scale=0.02) ->
        @source = $("##{@divId}").find ".MathJax_SVG"
        @svg = @source.find "svg"
        g = @svg.find "g"
        @group = $(g[0]).clone()
        @translate 0, 0

    viewBox: -> @svg[0].viewBox

    width: -> @scale * @viewBox().baseVal.width

    height: -> @scale * @viewBox().baseVal.height

    translate: (@dx, @dy) ->
        dy = @dy + (-@scale * @viewBox().baseVal.y)
        @group[0].setAttribute "transform", 
            "translate(#{@dx} #{dy}) scale(#{@scale}) matrix(1 0 0 -1 0 0)"

    appendTo: (diagram) ->
        diagram.append @group

【讨论】:

  • 你能解释一下这里发生了什么吗?如果这是一项简单的任务,我真的很想避免对 CoffeeScript 和 jQuery 的依赖。
  • nm,我想通了,有机会我会发布解耦解决方案
  • 你也可以阅读这个embeddedrelated.com/showarticle/599.php(我猜是@JasonS)
【解决方案3】:

我使用了以下代码,它定义了一个函数,该函数将乳胶代码作为输入并将经过 MathJax 处理的 svg 附加到目标 SVG 元素。

// First create a new element to hold the initial Latex code
// and eventual MathJax generated SVG. This element isn't added
// to the main docuemnt, so it's never seen.
let mathBuffer = document.createElement("div");

// Then define a function that takes LaTeX source code
// and places the resulting generated SVG in a target SVG element.
mathSVG = function (latex, target) {
  // Update the buffer with the source latex.
  mathBuffer.textContent = latex;
  // Get MathJax to process and typeset.
  MathJax.Hub.Queue(["Typeset", MathJax.Hub, mathBuffer]);
  // Queue a callback function that will execute once it's finished typesetting.
  MathJax.Hub.Queue(function () {
    // This (svg) is the generated graphics.
    const svg = mathBuffer.childNodes[1].childNodes[0];
    // The next line is optional, play with positioning as you see fit.
    svg.setAttribute("y", "-11pt");
    // Move the generated svg from the buffer to the target element.
    target.appendChild(svg);
    // Clear the buffer.
    mathBuffer.textContent = "";
  });
};

在上面,我假设一个包含 svg 元素的 html 宿主文档。它也应该适用于 svg 宿主文档。

【讨论】:

  • 您有没有机会知道如何将其翻译成 MathJax 3?它看起来很不错,但我喜欢使用 MathJax 3 更简洁的异步接口。
猜你喜欢
  • 2013-01-29
  • 1970-01-01
  • 2018-06-10
  • 1970-01-01
  • 1970-01-01
  • 2013-01-17
  • 2017-07-03
  • 2012-05-08
  • 1970-01-01
相关资源
最近更新 更多