dagda1
dagda1

Reputation: 28870

Mathjax not rendering inline labels

I am trying to render inline mathjax labels here along the x axis.

This is a react site and when the DOM is loaded, I have this code, I had to use setTimeout because MathJax is not available until I add the delay:

setTimeout(() => {
  MathJax.Hub.Config({
    tex2jax: {
      inlineMath: [ ['$','$'], ["\\(","\\)"] ],
      processEscapes: true
    }
  });
  MathJax.Hub.Queue(["Typeset", MathJax.Hub,], d3.select('.x.axis')[0][0]);
}, 500);

I create the labels like this using this code:

const xAxis = d3.svg.axis()
        .orient('bottom')
        .tickValues(xTickValues)
        .tickFormat((x) => '$\pi$')
        .scale(xScaleAxis);

I'm just trying to render pi at this stage but even that is not working. Mathjax is definitely doing something because when I view source, I see this on the tick value label:

<text dy=".71em" y="9" x="0" style="text-anchor: middle;"><span class="MathJax_Preview" style="color: inherit;"></span><span id="MathJax-Element-1-Frame" class="mjx-chtml MathJax_CHTML" tabindex="0" data-mathml="<math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;><mi>p</mi><mi>i</mi></math>" role="presentation" style="font-size: 116%; position: relative;"><span id="MJXc-Node-1" class="mjx-math" role="math" aria-hidden="true"><span id="MJXc-Node-2" class="mjx-mrow"><span id="MJXc-Node-3" class="mjx-mi"><span class="mjx-char MJXc-TeX-math-I" style="padding-top: 0.249em; padding-bottom: 0.496em;">p</span></span><span id="MJXc-Node-4" class="mjx-mi"><span class="mjx-char MJXc-TeX-math-I" style="padding-top: 0.434em; padding-bottom: 0.311em;">i</span></span></span></span><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>p</mi><mi>i</mi></math></span></span><script type="math/tex" id="MathJax-Element-1">pi</script></text>

But nothing is being displayed.

Upvotes: 0

Views: 817

Answers (1)

Mark
Mark

Reputation: 108567

I'm amazed at how difficult this is. While MathJax has an SVG renderer, it embeds the resulting svg in html. The hack I've come up with here, is to move it back into the tick after it's rendered.

setTimeout(() => {

  MathJax.Hub.Config({
    tex2jax: {
      inlineMath: [ ['$','$'], ["\\(","\\)"] ],
      processEscapes: true
    }
  });

  MathJax.Hub.Register.StartupHook("End", function() {
    setTimeout(() => {
          svg.selectAll('.x>.tick').each(function(){
          var self = d3.select(this),
              g = self.select('text>span>svg');
          g.remove();
          self.append(function(){
            return g.node();
          });
        });
      }, 1);
    });

  MathJax.Hub.Queue(["Typeset", MathJax.Hub,], d3.select('.x.axis').node());

}, 1);

Full code:

<!DOCTYPE html>
<meta charset="utf-8">
<style>

  .axis {
    font: 10px sans-serif;
  }
  
  .axis path,
  .axis line {
    fill: none;
    stroke: #000;
    shape-rendering: crispEdges;
  }
  
</style>

<body>
  <script src="//d3js.org/d3.v3.js"></script>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_SVG">
  </script>
  <script>
    var margin = {
        top: 10,
        right: 10,
        bottom: 10,
        left: 10
      },
      width = 500 - margin.left - margin.right,
      height = 200 - margin.top - margin.bottom;

    var x = d3.scale.linear()
      .domain([1,5])
      .range([0, width]);

    var y = d3.scale.linear()
      .range([height, 0]);

    var xAxis = d3.svg.axis()
      .scale(x)
      .orient("bottom")
      .tickFormat((x) => '$\\pi$')

   var svg = d3.select("body").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height/2 + ")")
      .call(xAxis);


setTimeout(() => {
  
  MathJax.Hub.Config({
    tex2jax: {
      inlineMath: [ ['$','$'], ["\\(","\\)"] ],
      processEscapes: true
    }
  });
  
  MathJax.Hub.Register.StartupHook("End", function() {
    setTimeout(() => {
          svg.selectAll('.x>.tick').each(function(){
          var self = d3.select(this),
              g = self.select('text>span>svg');
          g.remove();
          self.append(function(){
            return g.node();
          });
        });
      }, 1);
    });
  
  MathJax.Hub.Queue(["Typeset", MathJax.Hub,], d3.select('.x.axis').node());
  
}, 1);
    
    
  </script>

EDITS

I've extended this example on this block where I use MathJax and d3 to label the radians of a circle.

Upvotes: 1

Related Questions