MathJax inside SVG

白昼怎懂夜的黑 提交于 2019-12-03 02:34:30

Currently, the only way to include MathJax within an SVG diagram is through <foreignObject>. Yes, it is not ideal, not only because you need to provide a size, but also because IE9+ doesn't support <foreignObject>.

As for the SVG output, if you have used the MathJax contextual menu to select a math render, that will override the renderer choice in the document, so you may still be seeing HTML-CSS output for that reason. The value is stored in a cookie, so that it will be remembered from session to session. You can delete the cookie to remove the setting, or use the MathJax menu again to select SVG rendering.

Note, however, that this isn't going to help you either, as MathJax's SVG output is not just an SVG snippet that can be included into a larger SVG file, but include some HTML and the <svg> element itself. Moreover, MathJax needs the surrounding HTML to determine things like the font-size to use, and some other factors, so it is not going to be able to placed directly into your SVG diagram.

The <foreignObject> approach is really the only reliable way at the moment.

Edit: Here is a full example:

<!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>

There is a way to include MathJax SVG elements in an SVG diagram, without requiring foreignObject. A full demonstration of the technique is at http://puzlet.com/m/b00b3.

Say you have an SVG diagram like this (and containing any SVG elements) in your web page:

<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>

and the following MathJax:

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

Use this CoffeeScript (plus jQuery) to integrate the MathJax element into your SVG diagram:

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

You can also use the width() and height() methods for centering and vertical alignment.

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

I've used the following, which defines a function that takes latex code as input and appends the MathJax processed svg to a target SVG element.

// 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 = "";
  });
};

In the above, I'm assuming an html host document with svg elements within. It should also work in a svg host document too.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!