Write svg latex into a canvas html - html

My goal is to record maths scripts running on the canvas and at the same time record sound from the mic (I am a math teacher). I would like very much to allow latex formulas. Of course latex formulas do not write directly to canvas. MathJax can produce SVG elements. I wonder if it is possible to go from SVG->image->canvas, using javascript. I don't care if the obtained image on canvas is a little blured.
I couldn't find good examples of this yet on the internet.
Thanks!

Indeed there is no Latex to canvas direct way.
You can however draw an SVG over a canvas. See this Q/A to see how to proceed from an SVG in the DOM (which MathJax should give you).

Indeed that's possible. The trick here is to grab the SVG output of MathJax and draw it to a temporary <img> element, which in-turn is drawn to an on-screen canvas afterwards.
The actual <svg> element is a children of the <mjx-container> element returned by a call to MathJax's tex2svg() method.
Here's an example:
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let equation = "x = \\sin \\left( \\frac{\\pi}{2} \\right)";
let svg = MathJax.tex2svg(equation).firstElementChild;
let img = document.createElement('img');
img.onload = (e) => {
let tempWidth = e.target.naturalWidth;
let tempHeight = e.target.naturalHeight;
ctx.drawImage(e.target, canvas.width / 2 - tempWidth / 2, canvas.height / 2 - tempHeight / 2, tempWidth, tempHeight)
}
img.src = 'data:image/svg+xml;base64,' + btoa('<?xml version="1.0" encoding="UTF-8" standalone="no" ?>\n' + svg.outerHTML);
#canvas {
background-color: #eeeeee;
}
<script src="https://cdn.jsdelivr.net/npm/mathjax#3/es5/tex-svg.js" type="text/javascript"></script>
<canvas id="canvas"></canvas>

Related

Drawing a path of points html canvas

I made a double pendulum with canvas.
Here is the result: https://jsfiddle.net/zndo9vh4/
As you guys can see a trace is drawn everytime the second part of the pendulum moves, and my way of doing that is by appending each coordinate to a "trace" array.
var trace = []
trace.push([x2,y2]);
And then I draw the trace by joining each coordinate with the last one:
for (let i = 1; i < trace.length; i++) {
c.moveTo(trace[i][0], trace[i][1])
c.lineTo(trace[i-1][0], trace[i-1][1])
}
I want to improve it. What i've tried so far is only adding coordinates that aren't already in the array, but it's not a big improvent because the lines are drawn every loop
var trace = []
if(trace.includes([x2, y2]) != true){
trace.push([x2,y2]);
}
The way I think could be a good improvement is by having 2 canvas (I don't know if its possible) and then draw each point but only in that canvas so I doesnt have to be redrawn. But I dont know how to implement that.
Thanks in advice
Your improvement idea is great. You can indeed have two canvases!
There are two ways to go about it.
Offscreen canvas
Using what's called an offscreen canvas (a canvas that is created in JavaScript but not added to the DOM), you can draw all the points onto it and then using drawImage (which can accept a canvas element) pass the canvas to the main context.
var offscreenCanvas = document.createElement('canvas');
var offscreenC = offscreenCanvas.getContext('2d');
offscreenCanvas.width = canvas.width;
offscreenCanvas.height = canvas.height;
// in animate function, draw points onto the offscreen canvas instead
// of the regular canvas as they are added
if(trace.includes([x2, y2]) != true){
trace.push([x2,y2]);
var i = trace.length-1;
if (i > 1) {
offscreenC.strokeStyle = 'white'
offscreenC.beginPath();
offscreenC.moveTo(trace[i][0], trace[i][1])
offscreenC.lineTo(trace[i-1][0], trace[i-1][1])
offscreenC.stroke();
}
}
c.drawImage(offscreenCanvas, 0, 0);
Layered Canvases
One of the downsides to the offscreen canvas approach is that you have to draw it to the main canvas every frame. You can further improve the approach by layering two canvases on top of one another, where the top one is just the pendulum and the bottom one the trace.
This way, you never have to redraw the offscreen canvas onto the main canvas, and save yourself some rendering time.
Updated jsfiddle

SVG stroke width is messy on a html 5 canvas

I am trying to bind an SVG to a canvas. The SVG has a stroke width setup and it seems to be thicker than what it needs to be when bound to the canvas. What could be causing this and how to fix this?
The library that I use to bind svg to the html5 canvas is canvg
The JS fiddle below shows both the SVG and the bound svg on a canvas.
JS Fiddle: http://jsfiddle.net/fYAAf/111/
var image = new Image();
var canvas = document.createElement('canvas');
canvas.width =1090;
canvas.height = 1875;
var context = canvas.getContext('2d');
context.drawSvg(xml, 0, 0);
image.src = canvas.toDataURL();
According to the link: http://jsfiddle.net/fYAAf/111/
In the javascript code you are embedding the characteristic of SVG in a type tag (image). The result is something like this:

<img src="data:image/png;basQAACAnWQXByGjnghZGYT8......characteristic_of_SVG">
So you should try to put all the XML properties within an SVG tag, as it is written in the HTML document in the top of the example of jsFiddle.
In JavaScript something fast would:
var xml = "<svg> (Write here xml properties) <g><text (Write here text properties)><tspan dy="35" x="0">Test</tspan></text></g></svg>";
document.getElementById('container').innerHTML = xml;
<div id="container"></div>
I don't know what the cause of this behavior in img tags.

HTML5 Canvas Scaling using getImageData and putImageData

Is there any way to scale the canvas using getImageData and putImageData.Below is the snippet of code.
var c=document.getElementById("myCanvas");
var c2=document.getElementById("myCanvas2");
var ctx=c.getContext("2d");
var ctx2=c2.getContext("2d");
ctx.fillStyle="red";
ctx.fillRect(10,10,50,50);
function copy(){
var imgData=ctx.getImageData(10,10,50,50);
ctx2.translate(133.333,0);
ctx2.scale(0.75,1);
ctx2.putImageData(imgData,10,70);
}
I have tried this out http://jsbin.com/efixur/1/edit.
Thanks
Ajain
getImageData() and putImageData() are provided for raw pixel operations and thus scaling is not possible (unless you write a custom scaler in Javascript).
What you want is to use drawImage() and then use another <canvas> as source instead of <img>.
https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Using_images#Scaling

Drawing on HTML5 Canvas

Is there a putpixel functionality in html5. I have a canvas and want to draw on the canvas using mouse. How should I wright the javascript function for that. How can can I take the coordinate value on mouseclick and change the pixel value as soon as the user clicks.
From http://net.tutsplus.com/tutorials/javascript-ajax/canvas-from-scratch-pixel-manipulation/ section "Putting this into practice" using jquery:
$(canvas).click(function(e) {
var canvasOffset = $(canvas).offset();
var canvasX = Math.floor(e.pageX-canvasOffset.left);
var canvasY = Math.floor(e.pageY-canvasOffset.top);
// do here whatever you want
});
Read the article for a detailed explanation.
If you have a intermediate knowledge of Javascript try reading a tutorial like this:
http://www.williammalone.com/articles/create-html5-canvas-javascript-drawing-app/

How do I generate a thumbnail client-side in a modern browser?

I'm looking for an elegant way to generate a thumbnail for use with the FileAPI. Currently I get a DataURL representing an image. Problem is, if the image is very large, than moving it around and rerendering it becomes CPU intensive. I can see 2 options to get around this.
Generate a thumbnail on the client
Generate a thumbnail on the server, send the thumbnail back to the client (AJAX).
With HTML5 we have a canvas element? Does anyone know how to use it to generate thumbnails from pictures? They don't have to be perfect -- sampling quality is acceptable. Is there a jQuery plugin that will do this for me? Are there any other way to speed up the clientside use of large images?
I'm using HTML5, and Firefox 3.6+: there is no need to support anything other than Firefox 3.6+, please don't provide suggestions for IE 6.0
Here’s what you can do:
function getThumbnail(original, scale) {
var canvas = document.createElement("canvas");
canvas.width = original.width * scale;
canvas.height = original.height * scale;
canvas.getContext("2d").drawImage(original, 0, 0, canvas.width, canvas.height);
return canvas
}
Now, to create thumbnails, you simply do the equivalent of this:
var image = document.getElementsByTagName("img")[0];
var thumbnail = getThumbnail(image, 1/5);
document.body.appendChild(thumbnail);
Note: Remember to make sure that the image is loaded (using onload) before trying to make a thumbnail of it.
Okay, the way I can see this working is drawing the image to the canvas at a smaller size, then exporting the canvas. Say you want a 64px thumbnail:
var thumbSize = 64;
var canvas = document.getElementById("canvas");
canvas.width = thumbSize;
canvas.height = thumbSize;
var c = canvas.getContext("2d");
var img = new Image();
img.onload = function(e) {
c.drawImage(this, 0, 0, thumbSize, thumbSize);
document.getElementById("thumb").src = canvas.toDataURL("image/png");
};
img.src = fileDataURL;
With this code, an image element with the id "thumb" is used as the thumbnail element. fileDataURL is the data URL that you got from the file API.
More information on drawing images to the canvas: http://diveintohtml5.info/canvas.html#images
And on exporting canvas data: http://msdn.microsoft.com/en-us/library/ie/ff975241(v=vs.85).aspx