SVG stroke width is messy on a html 5 canvas - html

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.

Related

Write svg latex into a canvas 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>

HTML5 canvas text resizes

This must be obvious to most of you, so sorry for asking, but how come when I change the width of my canvas my text resizes as well? And how can I prevent this from happening?
code used:
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
context.fillText("text",10,10);
btw: before I get voted down / bashed at, I tried searching about this for like twenty minutes.. no results.
If you aren't re-sizing it using CSS You need to set the context font like so.
Live Demo
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
function drawText() {
ctx.font = 'italic 20px Calibri';
ctx.fillText("HELLO!", 100, 100);
}
window.addEventListener("resize", function() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
drawText()
});
drawText()​
If you are resizing the canvas element using css like the following example
canvas{
width:200px;
}
Then theres not much you can do to fix it. When you resize the canvas using CSS you just stretch it, but the pixel density stays the same. You should never use css to resize the canvas element, rather you should be using the width and height properties via JS like I do in my example above.
This problem might occur due to changing the attributes by using CSS. It seems that canvas gets re-scaled when you access its properties through css. I think your problem might be solved if you use this in your javascript code instead of changing it through css :
document.getElementById("yourCanvasId").height = 150; // height you want to change to
document.getElementById("yourCanvasId").width = 150; // width you want to change to
Same problem occurred with me. I did this and the problem was solved. Hope it helps !

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

html5 canvas drawing / saving

I'm attempting to turn the html5 canvas into a slide annotator. My goal is to upload an Image of a slide, allow the user to draw on it, and then save it.
Whats working: I successfully have slides being uploaded as background images and allowing the user to draw on them. I also have the save function working.
Whats wrong: Once the image is save, the drawing the user made stays but the background image doesn't become part of the saved image.
Is there a way to save the canvas to an image and keep the slide background in it? Perhaps its not supposed to be a background image?
Here is some of my code:
The Canvas + button:
<div id="main">
<canvas id="drop1" class="drop" style=" background: url(pdf_images/pdf-save-0.png); background-repeat:no-repeat;">
</canvas>
</div>
<input type="button" id="savepngbtn" value="Save Slide">
Saving the Canvas:
document.getElementById("savepngbtn").onclick = function() {
saveCanvas(oCanvas, "PNG");
}
function saveCanvas(pCanvas, strType) {
var bRes = false;
if (strType == "PNG")
bRes = Canvas2Image.saveAsPNG(oCanvas);
if (!bRes) {
alert("Sorry, this browser is not capable of saving " + strType + " files!");
return false;
}
}
you will need to make the 'background-image' part of the canvas if you would like to save them as a single image.
you can try something like:
var ctx = yourcanvas.getContext('2d');
var img = new Image();
img.src = 'http://yourimage.png';
img.onload = function() {
ctx.drawImage(img, 0, 0)
}
then allow the user to add the annotations and save.
It shouldn't be a background image.
You should use the canvas's provided DrawImage to draw an image. It's pretty simple to do so, just create a new image element (ie. new Image(), set the onload event to call DrawImage with itself as a parameter and then set the .src attribute so that it actually loads).
Obviously this should be the first thing you do as the image is kindof paramount to how the canvas works. You could add an additional hook within onload so as to not allow the user to do any drawing until the image has loaded.

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