saving mathml rendered to html5 canvas as png - html

My ultimate goal is to save rendered presentation MathML to a .PNG file. Knowing just enough about programming to be dangerous :-) there may be a better way to do this...I am drawing the equation on a canvas element, then trying to save the canvas element as a .PNG. I started with code found here -- https://developer.mozilla.org/en/HTML/Canvas/Drawing_DOM_objects_into_a_canvas -- and modified as follows:
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" style="border:2px solid black;" width="200" height="200">
</canvas>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var data = "<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'>" +
"<foreignObject width='100%' height='100%'>" +
"<div xmlns='http://www.w3.org/1998/Math/MathML' style='fontsize:40px'>" +
"<math>" +
"<mtable>" +
"<mtr>" +
"<mtd columnalign='right'>" +
"<mn>2</mn>" +
"<mi>x</mi>" +
"<mo>+</mo>" +
"<mn>3</mn>" +
"<mo>−</mo>" +
"<mn>3</mn>" +
"</mtd>" +
"<mtd columnalign='center'> " +
"<mo>=</mo>" +
"</mtd>" +
"<mtd columnalign='left'> " +
"<mn>9</mn>" +
"<mo>−</mo>" +
"<mn>3</mn>" +
"</mtd>" +
"</mtr>" +
"</mtable>" +
"</math>" +
"</div>" +
"</foreignObject>" +
"</svg>";
var svg = new (self.BlobBuilder || self.MozBlobBuilder || self.WebKitBlobBuilder);
var DOMURL = self.URL || self.webkitURL || self;
var img = new Image();
svg.append(data);
var url = DOMURL.createObjectURL(svg.getBlob("image/svg+xml;charset=utf-8"));
img.onload = function() {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
};
img.src = url;
window.open(canvas.toDataURL('image/png'));
</script>
</body>
</html>
If I comment out the window.open I can see the MathML in the canvas element, but the .PNG generated by the toDataURL is just transparent (no math equations). What am I missing? Thanks in advance...

Right off the bat the issue I see is that you defer the rendering of the canvas until the image loads, but you call window.open in the code without making sure its loaded. You would need to do something like the following
img.onload = function() {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
// now the image has been drawn for sure *before* opening the window
window.open(canvas.toDataURL('image/png'));
};
img.src = url;

Related

SVG custom polygon image stretch not working

I'm trying to both stretch and rotate an image into an SVG polygon (Basically an arc).
What I need is to stretch the image to fit, not tile or clip it.
What I'd like is :
The stretched/distorted image in the arc without the image clipped.
What I have is:
Clipped arc image
Here's the fiddle I've been working on -
https://jsfiddle.net/eLrgfnxb/57/
<svg style="overflow:visible; margin-left:111px; margin-top:22px; " height="1000" width="1000">
<defs>
<pattern id="blip1" patternUnits="userSpaceOnUse" width="100%" height="100%">
<image preserveAspectRatio="none" xlink:href="http://i.imgur.com/uTDpE6J.jpg" ></image>
</pattern>
</defs>
<polygon points="453,372 67,184 70,177 73,171 77,164 81,158 85,151 88,145 92,138 97,132 101,126 105,120 110,114 114,108 115,107" x="1" y="1" style="stroke-linejoin:round; fill:url(#blip1); stroke-width:2; stroke:hsl(212,45%,26%); ">
</polygon>
</svg>
I've seen a few ones:
How to stretch an image in a SVG shape to fill its bounds? (This is where I started, but doesn't handle the arc very well)
Image to fill a polygonal SVG shape (Also doesn't handle the complicated shape)
Resize image inside polygon point path(svg) and make it not clipped
I was thinking about switching to a canvas to see if that worked. I saw a couple interesting things here:
Stretch image to fit polygon html5 canvas
Thanks for the help!
After some work, I'm able to do it by going layer by layer through the image and putting it in an isosceles triangle. Then rotating it to about the right area.
Its a bit of a hairy assumption for the arc to be an isosceles, but lets make it better later.
Updated jfiddle - http://jsfiddle.net/gobfink/w1Lake9f/210/
<!DOCTYPE html>
<html>
<body>
<p>Tiger</p>
<!--
<img id="tiger" width="220" height="277" src="http://i.imgur.com/uTDpE6J.jpg" alt="the tiger" />
-->
<img id="tiger" width="340" height="429" src="http://i.imgur.com/uTDpE6J.jpg" alt="the tiger" />
<p>TigerCanvas:</p>
<canvas id="tigerCanvas" width="500" height="500" style="border:1px solid #d3d3d3;" >
</canvas>
<p>PolygonCanvas:</p>
<canvas id="polygonCanvas" width="500" height="500" style="border:1px solid #d3d3d3;" >
</canvas>
<p>PolygonTigerCanvas</p>
<canvas id="polygonTigerCanvas" width="1000" height="500" style="border:1px solid #d3d3d3;" >
</canvas>
<p>MousePosition: </p>
<canvas id="mousePositionCanvas" width="400" height="100" style="border:1px solid #d3d3d3;" >
</canvas>
<script>
window.onload = function() {
var p_canvas=document.getElementById("polygonCanvas");
var p_ctx = p_canvas.getContext("2d");
var p_maxX,p_minX, p_maxY, p_minY;
var poly_points = [[453,372] ,[67,184], [70,177], [73,171], [77,164], [81,158], [85,151], [88,145], [92,138], [97,132], [101,126], [105,120], [110,114], [114,108], [115,107]];
p_ctx.fillStyle='#f00';
p_ctx.beginPath();
p_ctx.moveTo(poly_points[0][0],poly_points[0],[1]);
poly_points.forEach(function(point) {
if (p_minX == null || point[0] < p_minX[0] ){
p_minX = point;
}
if (p_minY == null || point[1] < p_minY[1] ){
p_minY = point;
}
if (p_maxX == null || point[0] > p_maxX[0] ){
p_maxX = point;
}
if (p_maxY == null || point[1] > p_maxY[1] ){
p_maxY = point;
}
p_ctx.lineTo(point[0],point[1]) ;
});
console.log("p_minX: ", p_minX,", p_minY: ", p_minY, ", p_maxY: ", p_maxY, ", p_maxX: ", p_maxX);
p_ctx.closePath();
p_ctx.fill();
p_ctx.font= '8px serif';
p_ctx.fillStyle='#000';
p_ctx.fillText("maxX:" + p_maxX[0] + ","+ p_maxX[1] , p_maxX[0], p_maxX[1]);
p_ctx.fillText("minX:" + p_minX[0] + ","+ p_minX[1] , p_minX[0], p_minX[1]);
p_ctx.fillText("minY:" + p_minY[0] + ","+ p_minY[1] , p_minY[0], p_minY[1]);
//p_ctx.fillText(p_maxX[0] + ","+ p_maxX[1] , p_maxX[0], p_maxX[1]);
//p_ctx.fillText(p_maxX[0] + ","+ p_maxX[1] , p_maxX[0], p_maxX[1]);
var leg_distance = Math.floor(Math.hypot(p_maxX[0] - p_minX[0],p_maxX[1] - p_minX[1]));
var base_distance = Math.floor(Math.hypot(p_minX[0]- p_minY[0], p_minX[1]-p_minY[1]));
var arc_height = Math.floor(Math.sqrt(Math.pow(leg_distance,2) - Math.pow(base_distance/2,2)));
var p1 = [0,0];
var p2 = [base_distance,0];
var p3 = [base_distance/2, arc_height];
var p13_slope = (p3[1] - p1[1]) / (p3[0] - p1[0]);
var p13_intercept = p3[1] - p13_slope * p3[0];
var p23_slope = (p3[1] - p2[1]) / (p3[0] - p2[0]);
var p23_intercept = p3[1] - p23_slope * p3[0];
var orientation_angle = Math.asin((p_maxX[0] - p_minY[0]) /leg_distance);
console.log("leg_distance:",leg_distance,", base_distance: ", base_distance, ", arc_height: ", arc_height);
console.log("p1:", p1, ", p2: ",p2,", p3: ", p3);
console.log("p13_slope:", p13_slope, ", p13_intercept: ",p13_intercept);
console.log("p23_slope:", p23_slope, ", p23_intercept: ",p23_intercept);
console.log("orientation angle: ", orientation_angle);
var c = document.getElementById("tigerCanvas");
var ctx = c.getContext("2d");
var img = document.getElementById("tiger");
//var c_height = distance;
//var c_width = img.width/img.height * distance;
img.width = img.width/img.height * leg_distance ; //normalize the width
img.height = arc_height;
//ctx.drawImage(img, 1, 1);
ctx.drawImage(img, 1, 1,img.width,img.height);//, c_width, c_height);
var p_tiger_canvas = document.getElementById("polygonTigerCanvas");
var pt_ctx = p_tiger_canvas.getContext("2d");
//Assumes MaxX== MaxY
var slopeA = (p_maxX[1] - p_minX[1])/(p_maxX[0] - p_minX[0]) ;
var slopeB = (p_maxX[1] - p_minY[1])/(p_maxX[0] - p_minY[0]) ;
var inceptA = (p_maxX[1] - slopeA * p_maxX[0]);
var inceptB = (p_maxX[1] - slopeB * p_maxX[0]);
console.log("slopeA: ",slopeA, ", slopeB: ", slopeB, ", inceptA:", inceptA, "inceptB: ",inceptB);
console.log("img.width - ", img.width, " img.height -",img.height);
pt_ctx.font= '8px serif';
pt_ctx.fillStyle='#000';
p_ctx.fillText("maxX:" + p_maxX[0] + ","+ p_maxX[1] , p_maxX[0], p_maxX[1]);
p_ctx.fillText("minX:" + p_minX[0] + ","+ p_minX[1] , p_minX[0], p_minX[1]);
p_ctx.fillText("minY:" + p_minY[0] + ","+ p_minY[1] , p_minY[0], p_minY[1]);
//pt_ctx.translate(p_maxX[0]/4,p_maxX[1]);
pt_ctx.setTransform(1,0,0,1,p_minX[0],p_minX[1])
pt_ctx.rotate(-orientation_angle);
var i;
for (i = 0; i < arc_height; i++){
var Bx = (i - inceptB) / slopeB;
var Ax = (i - inceptA) / slopeA;
var p13x = (i - p13_intercept)/ p13_slope;
var p23x = (i - p23_intercept)/ p23_slope;
var d12_23= Math.hypot( p13x-p23x ,0);
var dAB = Math.hypot(Bx-Ax,0);
//console.log("i: ", i, ", Bx - ", Bx, ", Ax - ", Ax, ", dAB - ", dAB);
pt_ctx.drawImage(c,0,i,img.width,1,p13x,i,d12_23,1);
if (i % 10 == 0){
pt_ctx.fillText(Math.round(p13x) , p13x, i);
pt_ctx.fillText(Math.round(p23x) + ","+ i , p23x, i);
}
}
var mousePositionCanvas = document.getElementById('mousePositionCanvas');
function writeMessage(canvas, message) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
context.font = '18pt Calibri';
context.fillStyle = 'black';
context.fillText(message, 10, 25);
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
p_tiger_canvas.addEventListener('mousemove', function(evt) {
var mousePos = getMousePos(p_tiger_canvas, evt);
var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
writeMessage(mousePositionCanvas, message);
}, false)
}
</script>
</body>
</html>

Client X or ClientY has to be read like a pixel with his number. I don't where to add it without giving a syntax error

It's a simple problem, just an image with an event. The image have to follow the pointer.
<body>
<img src=https://media.giphy.com/media/MtQxKzhytFsmQ/giphy.gif alt="">
<script>
var bodi=document.querySelector("body")
var imag=document.querySelector("img")
bodi.addEventListener("mousemove",function(e) {
imag.style.left=e.clientX10px
imag.style.top=e.clientY
})
</script>
</body>
bodi.addEventListener("mousemove",function(e) {
imag.style.left = e.clientX + 'px';
imag.style.top = e.clientY + 'px';
})

Randomize background image using button onClick event

I want to randomize the background image when the user clicks a button.
Here's what I have.
Every time the button at the bottom right is cliked, I want to randomize the background image from a set array of externally hosted images.
How can I achieve that? (Without PHP, if possible.)
Try this method:
<script type="text/javascript">
function randomImg1() {
var myImages1 = new Array ();
myImages1[1] = "img/who/1.jpg";
myImages1[2] = "img/who/2.jpg";
myImages1[3] = "img/who/3.jpg";
var rnd = Math.floor( Math.random() * myImages1.length );
if( rnd == 0 ) {
rnd =1;
}
html_code = '<img class="who" src="' + myImages1[rnd] + '" />";
document.write(html_code);
}
</script>
You can also check out this
// EDIT -- By Pipskweak
instead of
html_code = '<img class="who" src="' + myImages1[rnd] + '" />";
document.write(html_code);
we could do this;
document.getElementsByTagName("body")[0].setAttribute('style','background-image: url(' + myImages1[rnd] + ')');
after all, background image was mentioned.

How to scale inline SVG

I want to scale inline SVG document in html. I have code like this:
var svg_width = svg.attr('width');
var svg_height = svg.attr('height');
function resize(width, height) {
svg.attr('width', width).attr('height', height);
var group = svg.find('#resize_group');
if (!group.length) {
group = svg.children().not('metadata, defs').wrapAll('<g/>').
parent().attr('id', 'resize_group');
}
var matrix = svg[0].createSVGMatrix();
//var matrix = group[0].getCTM();
matrix.a = width/svg_width;
matrix.d = width/svg_height;
group.attr('transform', matrix.asString());
}
SVGMatrix.prototype.asString = function() {
return 'matrix(' + this.a + ' ' + this.b + ' ' + this.c + ' ' + this.d +
' ' + this.e + ' ' + this.f + ')';
};
NOTE: I need to transform the elements inside svg because otherwise the image is trimmed.
but when I call resize function whole svg disappear. I've save svg to file and open it in Inkscape and it look normal (it's scaled). Why the svg disappear? (I tested on Firefox, Chrome and Opera)
I found quick hack, to replace svg with text of the svg to force redraw.
$.fn.xml = function() {
return (new XMLSerializer()).serializeToString(this[0]);
};
$.fn.SVGRedraw = function() {
return $(this.xml()).replaceAll(this);
};

Mootools: how to show tips manually

I would like to show a tooltip by calling it from code. Something like:
tips.fireEvent('show', el);
or
label.fireEvent('mouseover');
The tips are already set and stored on domready and work perfectly on mouseover. MooTools 1.4.5.
What worked was creating a new tip:
var tip_title = el.retrieve('tip:title');
var tip_text = el.retrieve('tip:text');
var tips = new Tips(el, {fixed: true, offset: {x: 0, y: size.y}});
var tip = tips.toElement();
tip.getFirst('div.tip').set('html', '<b>' + tip_title + '</b><br />' + tip_text);
var pos = el.getPosition();
var size = el.getSize();
tip.setStyles({left: pos.x, top: pos.y + size.y});
tips.show(el);
Then, just added a little extra code to detach the additional tip on mouseover.