Best way to use SVG or latex

Hello everyone,
I’m working on a project in which I need to draw latex dynamically on a playcanvas client.
Before going with playcanvas, i was using MathJax to convert my data and print it on html client.
Something like :

math to be print → latex → svg → html canvas on client.

Now, the problem i’m having is playcanvas can’t print SVG directly.
So i was looking for the easiest way to do it efficiently.
Is convert SVG to PNG/JPG the best solution ? Sharp seemed to be great for that, but it’s only work with node.js. And i can’t find a client side alternative.
Or should i generate my latex to image directly (so change MathJax to something else) ?
I noted Mathjax can also convert latex to html string.
I could also do the converting on server side, but i will need to download the image to everyclient, and I just want something not too complex.

What are you’re opinion ?

Maybe you can render SVG to an offscreen canvas and then generate an image from the canvas to use as a texture?

is there an API or a script that can do that ? With this kind of solution, i fear for portability or platform problem

It’s standard JS libraries so you should be able to find something on StackOverflow and the usual places :slight_smile:

@Dezra I am not totally familiar with latex or MathJax but… I know that inkscape can be used to convert your SVG to PNG.

well there is misunderstanding, I’m generating latex on live, on user request. so the SVG is not pre-rendered but printed dynamically.

Hi everyone,
I’m back to work on this project.

I’m trying to do thing like suggested here and I’m not succeeding so far. For now it look like :


Battle.prototype.testMathJaxAndSVGconvert = function () {
    //const toPNG = new Worker('toPNG.js'); I gave up on using worker... for now
    let svg = this.generateSVGFromLaTeX("\\sqrt[3]{8}=8^{\\frac{1}{3}}=2 ");
    console.log(svg);
    let width = 600;
    let height = 600;


    //  creating OffscreenCanvas
    const canvas = new OffscreenCanvas(width, height);
    const ctx = canvas.getContext('2d');


    //  Preparing to render the SVG on blob then to canvas
    var DOMURL = window.URL || window.webkitURL || window;
    var img1 = new Image();
    var blob = new Blob([svg], { type: 'image/svg+xml;charset=utf-8' });
    //var svg = new Blob([data], { type: 'image/svg+xml' });
    var url = DOMURL.createObjectURL(blob);
    console.log(blob);
    console.log(url);

    img1.onload = function () {
        ctx.drawImage(img1, 25, 70);
        DOMURL.revokeObjectURL(url);
    };
    img1.src = url;
    console.log(img1);

    console.log(canvas);
   // export my offscreen canvas to Png via a blob
    const blobPng = canvas.convertToBlob().then(blobPng => this.nextStep(blobPng));

};

this.nextStep :


Battle.prototype.nextStep = function (blobPng) {

    console.log(blobPng);
    pngUrl = URL.createObjectURL(blobPng);
    console.log(pngUrl);

    //applying resulting image to screen entity
    console.log('trying applying texture to screen entity');
    var textureAsset = new pc.Asset("texture", "texture", {
        url: pngUrl
    });
    this.app.assets.add(textureAsset);
    this.app.assets.load(textureAsset);

    let screen = this.app.root.findByName('imagePNG');
    screen.element.texture = textureAsset.resource;
};

generateSVGFromLaTeX,

 //here we convert string latex to svg with mathjax
Battle.prototype.generateSVGFromLaTeX = function (latex) {
    let math = MathJax.tex2svg(latex, {
        format: 'inline-TeX',
        display: false
    });
    console.log(math);
    return math;
};

But the screen imagePNG don’t show my generetad png.
I’m not sure where is problem is. With console.log i’have checked data at every step.
And even through it seem like all part to create SVG and turning it into PNG work, I’m probably doing not it efficiently, so I’m open to any recommendation.

I would visually check that every step is correct/as expected.

Have the canvas on screen so you can see what is being created in it
When generating the PNG, show it on screen as a simple <img> DOM element

Once you verify both, then getting it as a texture is pretty straightforward.

If you can share a project, that will help other users try to help you

Hi, thank you for your response.
Progress have been made since yesterday : I have threw away the whole OffScreenCanvas thing : it’s seem Canvas → Image progress rely on Blob object, so you should directly use it to convert SVG. It’s now much more simple :

       
Battle.prototype.generateMathImage = function (formula) {
    const svgData = new XMLSerializer().serializeToString(this.generateSVGFromLaTeX(formula));
    const blob = new Blob([svgData], { type: "image/svg+xml" });
    const imgResult = new File([blob], "MyEquation.png", { type: "image/png" });
    let urlImgResult = URL.createObjectURL(imgResult);

However, my current issue is that I am failing to use the resulting PNG file. It is throwing a DOMException: “An attempt was made to use an object that is not, or is no longer, usable.”

I think I know the reason :

// affecting resulting PNG to texture
    var textureAsset = new pc.Asset("texture", "texture", {
        url: pngUrl
    });
    console.log(textureAsset);

    this.app.assets.add(textureAsset);
    this.app.assets.load(textureAsset);

I suppose the last line need to acces my resulting file from a place where it cannot be accessed. But how should I do it ?

Here is a copy of my project files. Sry for the mess, it’s work in progress.
edit: Don’t be surprise, it will download a png file of the formula.

I’ve got a working version of it going: https://playcanvas.com/project/1036913/overview/f-math-project

You will have to play around with it more to get the size, position of it correct for your project.

I’ve removed a lot of the code to get to minimum working version.

Whoa, thank you really. I will check that more in detail tomorrow.