whats the difference between html2canvas and rasterizehtml.js - html

Apparently there are solutions to capturing screenshot of a web page:
Snapabug works by using an applet
GrabzIt I guess this is done on the server side.
Webkit2png is a command line tool, so not really part of the browser code.
There are probably other solutions that use ActiveX.
But I am interested in a Javascript only solution. From what I understand, both html2canvas and rasterizeHTML.js allow to convert html (in a web page) to an image. So, in what way is the implementation of html2canvas vs rasterizehtml.js different ? From what I understand both of them seem to use Canvas to generate the result. So in what way are they different? Which one is better ?

The main difference is that Rasterize is a wrapper around SVG foreignObject and html2canvas is essentially a reimplementation of browser HTML rendering from scratch. There are a lot of security headaches that Rasterize has to handle, but I think that its approach is better, as suggested by its being only 950 lines of code to html2canvas's 2400.
If the HTML you're rendering isn't very complex or doesn't need to be pixel-perfect, you may be able to skip Rasterize and use foreignObject directly, as described in MDN: Drawing DOM objects into a canvas:
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/1999/xhtml" style="font-size:40px">' +
'<em>I</em> like <span style="color:white; text-shadow:0 0 2px blue;">cheese</span>' +
'</div>' +
'</foreignObject>' +
'</svg>';
var DOMURL = window.URL || window.webkitURL || window;
var img = new Image();
var svg = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
var url = DOMURL.createObjectURL(svg);
img.onload = function () {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
}
img.src = url;

I tried html2canvas.js and rasterizeHTML.js for visualisation of a piece of html. Both have some issues, though. html2canvas.js can't get through with elements which have transformation (For example, text with css scale transform). As long as, I can't make rasterizeHTML.js to draw a canvas inside the canvas which displays the html.

Related

Implementing svg with applied filter

I'm having trouble with implementing a svg-file on a website: Every file displays fine if it has no filters set in Inkscape. Exporting to .png works fine for every file but when I'm trying to display a file with a filter all parts of the svg-file with filter are not displayed.
Example of file without filter (sorry for the links, but it seems I aint got enough reputation points to post images...):
and with filter set:
As you can see, the "upper part" is not displayed because of a (shadow-)filter.
So, is it possible to display svg-files with filters or do I have to use css-effects for example for shadow effects?
Many thanks
EDIT:
Here is my HTML:
<img class="svg" src="img/favlabel3.svg">
Javascript I use for svg:
jQuery('img.svg').each(function(){
var $img = jQuery(this);
var imgID = $img.attr('id');
var imgClass = $img.attr('class');
var imgURL = $img.attr('src');
jQuery.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = jQuery(data).find('svg');
// Add replaced image's ID to the new SVG
if(typeof imgID !== 'undefined') {
$svg = $svg.attr('id', imgID);
}
// Add replaced image's classes to the new SVG
if(typeof imgClass !== 'undefined') {
$svg = $svg.attr('class', imgClass+' replaced-svg');
}
// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr('xmlns:a');
// Replace image with new SVG
$img.replaceWith($svg);
}, 'xml');
});
The most likely explanation is that the Inkscape filters are using a feature not supported in web browsers, probably BackgroundImage (which allows a filter on one element to combine with elements behind it -- no browsers currently support it).
The specs do not offer any fallback options for filters, or any specific error handling guidelines. Most browsers respond to errors in a filter by making the filtered graphic disappear, as you can see if you try the example SVG from the specs. (Compare with the correctly rendered version as a PNG.)
You'll need to figure out an alternative way to create the filter effect without using the background image.

Canvas algorithm to plot signatures randomly like a signed yearbook?

I'm looking for the best approach to plot multiple signatures randomly on a page like a high school yearbook using Canvas or SVG. Anyone know of existing algorithms or open source code similar to this?
Did you look into the following javascript libraries? I've used both of them and they work quite well:
SignaturePad or jSignature
Both of the offer a fallback to flash if the browser doesn't support it. We have chosen jSignature since the overall performance on different tablets when drawing new signature was better, but I personally like the style & API of signaturePad better.
You can record the signatures as example on a secured admin page and then just plot them wherever you want them.
Update
Since you just want random strings and not really signatures I recommend you'll have a look at HTML5 Canvas – Arrays and Random text:
<!DOCTYPE html>
<html>
<head>
<title>Random Text</title>
<script type="text/javascript">
var canvas, ctx;
var quotes = new Array();
var img = new Image(); // Create new img element
//or you can also use:
//var quotes = [];
function setup(){
//canvas and context setup
canvas=document.getElementById("myCanvas");
ctx=canvas.getContext("2d");
//create values for the array
quotes[0]="I";
quotes[1]="think";
quotes[2]="you";
quotes[3]="always";
quotes[4]="have";
quotes[5]="regrets";
//function calls
setInterval(draw,300);
window.addEventListener("keydown",checkKeyboard);
}
function draw(){
var randomIndex = Math.floor(Math.random()*quotes.length);
var randomColor = Math.round(Math.random()*80);
var randomX = Math.random()*canvas.width;
var randomY = Math.random()*canvas.height*2-canvas.width/2;
var randomSize = Math.random()*30+10;
ctx.fillStyle="rgba(255,255,255,0.8)";
ctx.font=randomSize+"px Arial Black, Gadget, sans-serif";
ctx.fillText(quotes[randomIndex],randomX,randomY);
ctx.lineWidth=1;
//ctx.strokeText(quotes[randomIndex],randomX,randomY);
}
function checkKeyboard(myEvt){
if(myEvt.keyCode==13){
ctx.clearRect(0,0,canvas.width,canvas.height);
}
}
</script>
</head>
<body onload="setup()">
<canvas id="myCanvas" width="800" height="600" style="border:1px solid; background:url(bg-hand.jpg)"></canvas>
<p>Press "ENTER" to clear the canvas</p>
</body>
</html>

Storing HTML5 canvas containing images

How do you store a canvas that contains images using the toDataURL method? Everything works fine for text and drawing, but I don't know how to handle images. Any help would be appreciated. Thanks
I have modified my question as follows:
This works when the image is pulled directly from a .png. However, when I call the Google Charts API, toDataURL doesn't work even though the image renders correctly on the canvas. Google Charts is returning a .png. Anyone have any ideas? Thanks.
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" charset="utf-8">
function test() {
var c = document.getElementById("drawing-canvas");
var cxt = c.getContext("2d");
// This doesn't work.
//var imgsrc = 'http://chart.apis.google.com/chart?cht=tx&chf=bg,s,ffffff&chco=000000&
chl=a';
// This works
var imgsrc = 'chart.png';
var img = new Image();
img.src = imgsrc;
cxt.drawImage(img,0,0);
}
function wr() {
var cc = document.getElementById("drawing-canvas");
var url = cc.toDataURL();
var newImg = document.createElement("img");
newImg.src = url;
document.body.appendChild(newImg);
}
</script>
</head>
<body onload = "test();">
<canvas id="drawing-canvas" width = "500px" height = "500px" style="background-color:
#ffffff; border: 2px solid #000000;">
Your browser does not support the canvas element.
</canvas>
<input type = "button" value = "go" onclick = "wr();">
</body>
</html>
First of all, your chart didn't even render on the canvas when I tested it. You need to wait for the image to load. Your chart.png image probably loads instantaneously since it's cached, but the one generated by Google Charts API isn't. This is what you should do:
var img = new Image();
img.onload = function()
{
cxt.drawImage(img,0,0);
}
img.src = imgsrc;
Aside from that, you must be getting a SECURITY_ERR in your browser's console. This is because the Canvas security model doesn't allow you to export images coming from an external URL. You should use a server-side language to save the Google Charts image to your server, then load it from there.
The HTML canvas element has a method called toDataURL, that will return a data URL image representing the canvas. You can check the documentation API on the MDN.
Specifically, it says about toDataURL:
toDataURL(in optional DOMString type, in any ...args)
returns DOMString
Returns a data: URL containing a representation of the image in the format specified by type (defaults to PNG).
If the height or width of the canvas is 0, "data:," representing the empty string, is returned.
If the type requested is not image/png, and the returned value starts with data:image/png, then the requested type is not supported.
Chrome supports the image/webp type.
If the requested type is image/jpeg or image/webp, then the second argument, if it is between 0.0 and 1.0, is treated as indicating image quality; if the second argument is anything else, the default value for image quality is used. Other arguments are ignored.
And provides and example on how to use it:
function test() {
var canvas = document.getElementById("canvas");
var url = canvas.toDataURL();
var newImg = document.createElement("img");
newImg.src = url;
document.body.appendChild(newImg);
}
In this example, we use the dataURL as the source attribute of an img element, but you can do whatever you want you it (like storing it somewhere, or sending it to the server with an ajax call).
Note that most of the methods involved in drawing on canvas are methods of drawing context (obtained by a call to getContext), while this method is one of the canvas element.

Crop image to canvas

I have 2 divs
<div id="image-orig">
<img src="image_example.jpg"/>
</div>
<div id="image-crop">
<canvas id="preview" style="width:548px;height:387px"></canvas>
</div>
image_example.jpg can be image any size.
function updatePreview(c) {
if(parseInt(c.w) > 0) {
var orig = $("#image-orig img")[0];
var canvas = $("#image-crop canvas")[0];
var context = canvas.getContext("2d");
context.drawImage(orig,
c.x*coeff,c.y*coeff,c.w*coeff,c.h*coeff,
0,0,canvas.width,canvas.height
);
}
}
$(function(){
$('#image-orig img').Jcrop({
onSelect: updatePreview,
onChange: updatePreview,
aspectRatio : parseFloat($('#image-orig img').width()/$('#image-orig img').height())
});
});
coeff - it's coefficient if size image larger div preview.
That's problem:
http://dbwap.ru/3725988.png
In second div (canvas). Quality image very low.
SOLUTION IS FOUND
canvas.width = c.w*coeff;
canvas.height = c.h*coeff;
context.drawImage(orig,
c.x*coeff,c.y*coeff,c.w*coeff,c.h*coeff,
0,0,c.w*coeff,c.h*coeff
);
$(that.el).find("#ImageCode").attr('src', canvas.toDataURL());
$(that.el).find("#ImageCode").show();
I'm just creating image tag and copying from canvas to image.
If you have access to .net, you can modify the way your new images are saved with JCrop:
http://mironabramson.com/blog/post/2009/04/Cropping-image-using-jQuery,-Jcrop-and-ASPNET.aspx
Solution available to you without using server-side (.net / php):
First, make sure that when you use JCrop that you have html5 canvas image smoothing enabled:
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html
If that is already set, or has no effect, then I think your only other options to investigate image option available to you through each browser:
Enable smoothing in Mozilla - See this article as an example (look for 'mozImageSmoothingEnabled'):https://developer.mozilla.org/en/Canvas_tutorial/Using_images#Controlling_image_scaling_behavior
Apply filters in IE: http://code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/
Note: There may be some sort of Flash solution that could work but it would probably be too difficult to combine any Flash solution with JCrop and html5 canvas.

printing just canvas element on a page

im a little stuck using the canvas element in html5, have scoured the net looking for a workable solution but to no avail!
the main issue is that I want to click a button and send just the canvas element on the page to the printer.
i have tried using toDataUrl() - but this just seems to be resulting in a blank white image which has none of the canvas content!
the other issue i am experiencing is that attempting to initiate any javascript functions using "onClick" attached to a form button seems to be being tempermental at best!
here is my current attempt - this works in the sense that it does open a new window and attempt to send it to printer and it does create a base64 string (tested this using the "dataUrl" output on the second lowest document.write line) but as previously mentioned the image appears to be completely blank! (the canvas itself is definitely filled, both with an imported image and some text)
function printCanv()
{
var dataUrl = document.getElementById('copy').toDataURL(); //attempt to save base64 string to server using this var
document.getElementById('testBox').value = dataUrl; //load data into textarea
//attempt open window and add canvas etc
win = window.open();
self.focus();
win.document.open();
win.document.write('<'+'html'+'><'+'head'+'><'+'style'+'>');
win.document.write('body, td { font-family: Verdana; font-size: 10pt;}');
win.document.write('<'+'/'+'style'+'><'+'/'+'head'+'><'+'body'+'>');
((image code is here but site will not let me post it for some reason?))
win.document.write(dataUrl);
win.document.write('<'+'/'+'body'+'><'+'/'+'html'+'>');
win.document.close();
win.print();
win.close();
}
note: the code from "win = window.open()" onwards is currently taken from a tutorial and not my own work!
it is currently being called using <body onload="printCanv";"> - for some reason I could not get this to work at all using a button (little chunk of code below is my attempt which seemed to fail)
<input type="button" id="test" value="click me" onClick="printCanv();"> </input>
apologies is this help request is all over the place! i haven't posted to a site like this before and it didn't like me posting some html/script!
thanks in advance for any help you may be able to offer :)
Edit: draw function:
function copydraw() { //function called "copydraw" (could be anything)
var testimage3 = document.getElementById('copy').getContext('2d'); //declare variable for canvas overall (inc paths)
var img3 = new Image(); //declare image variable called "img3"
var testVar = document.getElementById('userIn').value; //take value from userin box. only updating on browser refresh?
img3.onload = function(){ //when image has loaded (img.onload) run this function
testimage3.drawImage(img3,0,0); //draw "img" to testimage
testimage3.font = "30pt 'Arial'"; //font method varies font attrib (weight, size, face)
testimage3.fillStyle = "#000000"; //sets fill color
testimage3.fillText(testVar, 310, 360); //filltext method draws text (xup ydown)
}
img3.src = 'images/liecakeA4.jpg'; //source of image
}
This function works perfectly, it draws the object and adds text from the variable, but for some reason it seems to be preventing me from outputting it as an image. I'm really confused!
I'm not sure exactly what's wrong with your code, I suspect in your current version calling printCanv in the body load event will mean you're trying to print the canvas before it's drawn. Running it off the button should work better, I'm not sure why that wasn't working for you as there's no reason in principle why it shouldn't work.
To arrive at a working version I've modified your code slightly:
function printCanvas(el) {
var dataUrl = document.getElementById(el).toDataURL(); //attempt to save base64 string to server using this var
var windowContent = '<!DOCTYPE html>';
windowContent += '<html>'
windowContent += '<head><title>Print canvas</title></head>';
windowContent += '<body>'
windowContent += '<img src="' + dataUrl + '">';
windowContent += '</body>';
windowContent += '</html>';
var printWin = window.open('','','width=340,height=260');
printWin.document.open();
printWin.document.write(windowContent);
printWin.document.close();
printWin.focus();
printWin.print();
printWin.close();
}
This works for me in the Firefox 4.0 nightly.
One addition to the accepted-best-answer: It doesnt work here with Chrome 17.0.942.0 winvista, because the print-preview-dlg is shown within the website itself and printWin.close() will close the dlg too.
So printWin.close() must be delayed or initiated by the user, but those are no good solutions.
It would be best, if chrome printdlg could have a callback, sth. one knows, printing is done, and can close the window. If this is possible is another question.