26

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

我希望使用 MathJax 呈现这些 SVG 图表中的文本元素。我知道如何渲染动态数学。但是,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 元素。

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

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

4

3 回答 3

13

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

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

但是请注意,这也对您没有帮助,因为 MathJax 的 SVG 输出不仅仅是可以包含到更大 SVG 文件中的 SVG 片段,还包含一些 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>
于 2013-04-12T14:11:29.330 回答
4

有一种方法可以在 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
于 2014-02-21T00:55:45.353 回答
1

我使用了以下内容,它定义了一个函数,该函数将乳胶代码作为输入并将 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 主机文档中工作。

于 2018-08-24T20:02:16.500 回答