initial commit

This commit is contained in:
Niklas von Hertzen 2011-07-16 04:13:38 +03:00
commit 578cd17223
9 changed files with 3736 additions and 0 deletions

2364
demo.html Normal file

File diff suppressed because it is too large Load Diff

188
demo2.html Normal file
View File

@ -0,0 +1,188 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script type="text/javascript" src="html2canvas.js"></script>
<script type="text/javascript" src="jquery.plugin.html2canvas.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('body').html2canvas();
// var ss = $('ul').offset();
// alert(ss.left);
});
</script>
<title>
display/box/float/clear test
</title>
<style type="text/css">
/* last modified: 1 Dec 98 */
html {
font: 10px/1 Verdana, sans-serif;
background-color: blue;
color: white;
}
body {
margin: 1.5em;
border: .5em solid black;
padding: 0;
width: 48em;
background-color: white;
}
dl {
margin: 0;
border: 0;
padding: .5em;
}
dt {
background-color: rgb(204,0,0);
margin: 0;
padding: 1em;
width: 10.638%; /* refers to parent element's width of 47em. = 5em or 50px */
height: 28em;
border: .5em solid black;
float: left;
}
dd {
float: right;
margin: 0 0 0 1em;
border: 1em solid black;
padding: 1em;
width: 34em;
height: 27em;
}
ul {
margin: 0;
border: 0;
padding: 0;
}
li {
display: block; /* i.e., suppress marker */
color: black;
height: 9em;
width: 5em;
margin: 0;
border: .5em solid black;
padding: 1em;
float: left;
background-color: #FC0;
}
#bar {
background-color: black;
color: white;
width: 41.17%; /* = 14em */
border: 0;
margin: 0 1em;
}
#baz {
margin: 1em 0;
border: 0;
padding: 1em;
width: 10em;
height: 10em;
background-color: black;
color: white;
}
form {
margin: 0;
display: inline;
}
p {
margin: 0;
}
form p {
line-height: 1.9;
}
blockquote {
margin: 1em 1em 1em 2em;
border-width: 1em 1.5em 2em .5em;
border-style: solid;
border-color: black;
padding: 1em 0;
width: 5em;
height: 9em;
float: left;
background-color: #FC0;
color: black;
}
address {
font-style: normal;
}
h1 {
background-color: black;
color: white;
float: left;
margin: 1em 0;
border: 0;
padding: 1em;
width: 10em;
height: 10em;
font-weight: normal;
font-size: 1em;
}
</style>
</head>
<body>
<dl>
<dt>
toggle
</dt>
<dd>
<ul>
<li>
the way
</li>
<li id="bar">
<p>
the world ends
</p>
<form action="./" method="get">
<p>
bang
<input type="radio" name="foo" value="off">
</p>
<p>
whimper
<input type="radio" name="foo2" value="on">
</p>
</form>
</li>
<li>
i grow old
</li>
<li id="baz">
pluot?
</li>
</ul>
<blockquote>
<address>
bar maids,
</address>
</blockquote>
<h1>
sing to me, erbarme dich
</h1>
</dd>
</dl>
<p style="color: black; font-size: 1em; line-height: 1.3em; clear: both">
This is a nonsensical document, but syntactically valid HTML 4.0. All 100% conformant CSS1 agents should be able to render the document elements above this paragraph <b>indistinguishably</b> (to the pixel) from this reference rendering, (except font rasterization and form widgets). All discrepancies should be traceable to CSS1 implementation shortcomings. Once you have finished evaluating this test, you can return to the <A HREF="sec5526c.htm" style="text-decoration:none">parent page</A>.
</p>
</body>
</html>

79
demo3.html Normal file
View File

@ -0,0 +1,79 @@
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.js"></script>
<script type="text/javascript" src="html2canvas.js"></script>
<script type="text/javascript" src="jquery.plugin.html2canvas.js"></script>
<script type="text/javascript">
$(function(){
$('body').html2canvas();
});
</script>
<style>
.feedback-overlay-black{
background-color:#000;
opacity:0.5;
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
margin:0;
}
</style>
<style>
div{
padding:20px;
margin:0 auto;
border:5px solid black;
}
h1{
border-bottom:2px solid white;
}
h2{
background: #efefef;
padding:10px;
}
</style>
</head>
<body>
<div style="background:red;">
<div style="background:green;">
<div style="background:blue;border-color:white;">
<div style="background:yellow;"><div style="background:orange;"><h1>Heading</h1>
Text that isn't wrapped in anything.
<p>Followed by some text wrapped in a <b>&lt;p&gt; paragraph.</b> </p>
Maybe add a <a href="#">link</a> or a different style of <a href="#" style="background:white;" id="highlight">link with a highlight</a>.
<hr />
<h2>More content</h2>
<div style="width:10px;height:10px;border-width:10px;padding:0;">a</div>
</div></div>
</div>
</div>
</div>
</body>
</html>

795
html2canvas.js Normal file
View File

@ -0,0 +1,795 @@
/*
* html2canvas v0.11 <http://html2canvas.hertzen.com>
*
* Copyright 2011, Niklas von Hertzen <http://hertzen.com>
* http://www.twitter.com/niklasvh
*
* Released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
function html2canvas(el,userOptions) {
var options = userOptions || {};
var opts = {
logging:false,
ready: function(canvas){
document.body.appendChild(canvas);
},
renderViewport: true
};
opts = extendObj(options,opts);
var imageLoaded,
imagesLoaded = 0,
images = [],
canvas,
ctx,
bgx,
bgy,
image,
ignoreElements = "IFRAME|OBJECT|PARAM";
// test how to measure text bounding boxes
var useRangeBounds = false;
if (document.createRange){
var r = document.createRange();
useRangeBounds = new Boolean(r.getBoundingClientRect);
}
function init(){
canvas = document.createElement('canvas');
// TODO remove jQuery dependency
canvas.width = $(document).width();
canvas.height = $(document).height()+10;
if (!canvas.getContext){
// TODO include Flashcanvas
/*
var script = document.createElement('script');
script.type = "text/javascript";
script.src = "flashcanvas.js";
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(script, s);
if (typeof FlashCanvas != "undefined") {
FlashCanvas.initElement(canvas);
ctx = canvas.getContext('2d');
}
*/
}else{
ctx = canvas.getContext('2d');
}
if (!ctx){
// canvas not initialized, let's kill it here
log('Canvas not available');
return;
}
// set common settings for canvas
ctx.textBaseline = "bottom";
log('Finding background images');
getImages(el);
log('Finding images');
each(document.images,function(i,e){
preloadImage(getAttr(e,'src'));
});
if (images.length == 0){
start();
}
}
function start(){
if (images.length == 0 || imagesLoaded==images.length/2){
log('Started parsing');
newElement2(el);
parseElement(el);
}
}
function log(a){
if (opts.logging){
if (typeof console != "undefined" && console.log){
console.log(a);
}else{
alert(a);
}
}
}
function preloadImage(src){
if (images.indexOf(src)==-1){
images.push(src);
var img = new Image();
// TODO remove jQuery dependancy
$(img).load(function(){
imagesLoaded++;
start();
});
img.onerror = function(){
images.splice(images.indexOf(img.src),2);
imagesLoaded++;
start();
}
img.src = src;
images.push(img);
}
}
/*
* Function to find all images from <img> and background-image
*/
function getImages(el){
// TODO remove jQuery dependancy
each($(el).contents(),function(i,element){
var ignRe = new RegExp("("+ignoreElements+")");
if (!ignRe.test(element.nodeName)){
getImages(element);
}
})
if (el.nodeType==1 || typeof el.nodeType == "undefined"){
var background_image = getCSS(el,'background-image');
if (background_image && background_image != "1" && background_image != "none" && background_image.substring(0,7)!="-webkit"){
var src = backgroundImageUrl(background_image);
preloadImage(src);
}
}
}
function parsing(el){
var ignRe = new RegExp("("+ignoreElements+")");
if (!ignRe.test(el.nodeName)){
newElement2(el);
// TODO remove jQuery dependancy
var contents = $(el).contents();
if (contents.length == 1){
// check nodeType
if (contents[0].nodeType==1){
// it's an element, so let's look inside it
parsing(contents[0]);
}else if (contents[0].nodeType==3){
// it's a text node, so lets print the text
newText2(el,contents[0]);
}
}else{
each(contents,function(cid,cel){
if (cel.nodeType==1){
// element
parsing(cel);
}else if (cel.nodeType==3){
newText2(el,cel);
}
});
}
}
}
function parseElement(element){
each(element.children,function(index,el){
parsing(el);
});
finish();
}
/*
* Function to retrieve the actual src of a background-image
*/
function backgroundImageUrl(src){
if (src.substr(0,5)=='url("'){
src = src.substr(5);
src = src.substr(0,src.length-2);
}else{
src = src.substr(4);
src = src.substr(0,src.length-1);
}
return src;
}
/*
* Load image from storage
*/
function loadImage(src){
var imgIndex = images.indexOf(src);
if (imgIndex!=-1){
return images[imgIndex+1];
}else{
return false;
}
}
/*
* Function to provide bounds for element
*/
function getBounds(el){
window.scroll(0,0);
if (el.getBoundingClientRect){
var bounds = el.getBoundingClientRect();
bounds.top = bounds.top;
bounds.left = bounds.left;
return bounds;
}else{
// TODO remove jQuery dependancy
var p = $(el).offset();
return {
left: p.left + parseInt(getCSS(el,"border-left-width"),10),
top: p.top + parseInt(getCSS(el,"border-top-width"),10),
width:$(el).innerWidth(),
height:$(el).innerHeight()
}
}
}
function newElement2(el){
var bounds = getBounds(el);
var x = bounds.left;
var y = bounds.top;
var w = bounds.width;
var h = bounds.height;
var bgcolor = getCSS(el,"background-color");
/*
* TODO add support for different border-style's than solid
*/
var borders = getBorderData(el);
each(borders,function(borderSide,borderData){
if (borderData.width>0){
var bx = x,
by = y,
bw = w,
bh = h-(borders[2].width);
switch(borderSide){
case 0:
// top border
bh = borders[0].width;
break;
case 1:
// right border
bx = x+w-(borders[1].width);
bw = borders[1].width;
break;
case 2:
// bottom border
by = (by+h)-(borders[2].width);
bh = borders[2].width;
break;
case 3:
// left border
bw = borders[3].width;
break;
}
newRect(bx,by,bw,bh,borderData.color);
}
});
// draw base element bgcolor
newRect(
x+borders[3].width,
y+borders[0].width,
w-(borders[1].width+borders[3].width),
h-(borders[0].width+borders[2].width),
bgcolor
);
drawBackground(el,{
left: x+borders[3].width,
top: y+borders[0].width,
width: w-(borders[1].width+borders[3].width),
height: h-(borders[0].width+borders[2].width)
});
if (el.nodeName=="IMG"){
image = loadImage(getAttr(el,'src'));
if (image){
ctx.drawImage(image,x+parseInt(getCSS(el,'padding-left'),10),y+parseInt(getCSS(el,'padding-top'),10));
}else{
log("Error loading <img>:" + getAttr(el,'src'));
}
}
}
function drawBackground(el,bounds){
var background_image = getCSS(el,"background-image");
var background_repeat = getCSS(el,"background-repeat");
if (typeof background_image != "undefined" && /^(1|none)$/.test(background_image)==false){
background_image = backgroundImageUrl(background_image);
var image = loadImage(background_image);
var bgp = getBackgroundPosition(el,bounds,image);
if (image){
switch(background_repeat){
case "repeat-x":
drawbackgroundRepeatX(image,bgp,bounds.left,bounds.top,bounds.width,bounds.height);
break;
case "repeat-y":
drawbackgroundRepeatY(image,bgp,bounds.left,bounds.top,bounds.width,bounds.height);
break;
case "no-repeat":
drawBackgroundRepeat(image,bgp.left+bounds.left,bgp.top+bounds.top,Math.min(bounds.width,image.width),Math.min(bounds.height,image.height),bounds.left,bounds.top);
// ctx.drawImage(image,(bounds.left+bgp.left),(bounds.top+bgp.top));
break;
default:
var height,
add;
bgp.top = bgp.top-Math.ceil(bgp.top/image.height)*image.height;
for(bgy=(bounds.top+bgp.top);bgy<=bounds.height+bounds.top;){
var h = Math.min(image.height,(bounds.height+bounds.top)-bgy);
if ( Math.floor(bgy+image.height)>h+bgy){
height = (h+bgy)-bgy;
}else{
height = image.height;
}
// console.log(height);
if (bgy<bounds.top){
add = bounds.top-bgy;
bgy = bounds.top;
}else{
add = 0;
}
drawbackgroundRepeatX(image,bgp,bounds.left,bgy,bounds.width,height);
if (add>0){
bgp.top += add;
}
bgy = Math.floor(bgy+image.height)-add;
}
break;
}
}else{
log("Error loading background:" + background_image);
//console.log(images);
}
}
}
function drawbackgroundRepeatY(image,bgp,x,y,w,h){
var height,
width = Math.min(image.width,w);
bgp.top = bgp.top-Math.ceil(bgp.top/image.height)*image.height;
for(bgy=(y+bgp.top);bgy<=h+y;){
if ( Math.floor(bgy+image.height)>h+y){
height = (h+y)-bgy;
}else{
height = image.height;
}
drawBackgroundRepeat(image,x+bgp.left,bgy,width,height,x,y);
bgy = Math.floor(bgy+image.height);
}
}
function drawbackgroundRepeatX(image,bgp,x,y,w,h){
var height = Math.min(image.height,h),
width;
bgp.left = bgp.left-Math.ceil(bgp.left/image.width)*image.width;
for(bgx=(x+bgp.left);bgx<=w+x;){
if (Math.floor(bgx+image.width)>w+x){
width = (w+x)-bgx;
}else{
width = image.width;
}
drawBackgroundRepeat(image,bgx,(y+bgp.top),width,height,x,y);
bgx = Math.floor(bgx+image.width);
}
}
function drawBackgroundRepeat(image,x,y,width,height,elx,ely){
var sourceX = 0,
sourceY=0;
if (elx-x>0){
sourceX = elx-x;
}
if (ely-y>0){
sourceY = ely-y;
}
ctx.drawImage(
image,
sourceX, // source X
sourceY, // source Y
width-sourceX, // source Width
height-sourceY, // source Height
x+sourceX, // destination X
y+sourceY, // destination Y
width-sourceX, // destination width
height-sourceY // destination height
);
}
/*
* Function to retrieve background-position, both in pixels and %
*/
function getBackgroundPosition(el,bounds,image){
var bgposition = getCSS(el,"background-position").split(" "),
top,
left,
percentage;
if (bgposition[0].indexOf("%")!=-1){
percentage = (parseFloat(bgposition[0])/100);
left = ((bounds.width * percentage)-(image.width*percentage));
}else{
left = parseInt(bgposition[0],10);
}
if (bgposition[1].indexOf("%")!=-1){
percentage = (parseFloat(bgposition[1])/100);
top = ((bounds.height * percentage)-(image.height*percentage));
}else{
top = parseInt(bgposition[1],10);
}
return {
top: top,
left: left
};
}
/*
* Function to provide border details for an element
*/
function getBorderData(el){
var borders = [];
each(["top","right","bottom","left"],function(i,borderSide){
borders.push({
width: parseInt(getCSS(el,'border-'+borderSide+'-width'),10),
color: getCSS(el,'border-'+borderSide+'-color')
});
});
return borders;
}
// Drawing a rectangle
function newRect(x,y,w,h,bgcolor){
if (bgcolor!="transparent"){
ctx.fillStyle = bgcolor;
ctx.fillRect (x, y, w, h);
}
}
/*
* Function to draw the text on the canvas
*/
function printText(currentText,x,y){
if (trim(currentText).length>0){
ctx.fillText(currentText,x,y);
}
}
/*
* Function for fetching the css attribute
* TODO remove jQuery dependancy
*/
function getCSS(el,attribute){
return $(el).css(attribute);
}
/*
* Function for fetching the element attribute
*/
function getAttr(el,attribute){
return el.getAttribute(attribute);
//return $(el).attr(attribute);
}
function newText2(el,textNode){
var family = getCSS(el,"font-family");
var size = getCSS(el,"font-size");
var color = getCSS(el,"color");
var bold = getCSS(el,"font-weight");
var font_style = getCSS(el,"font-style");
var text_decoration = getCSS(el,"text-decoration");
// apply text-transform:ation to the text
textNode.nodeValue = textTransform(textNode.nodeValue,getCSS(el,"text-transform"));
var text = textNode.nodeValue;
//text = $.trim(text);
if (text.length>0){
switch(bold){
case "401":
bold = "bold";
break;
}
ctx.font = bold+" "+font_style+" "+size+" "+family;
ctx.fillStyle = color;
var oldTextNode = textNode;
for(var c=0;c<text.length;c++){
var newTextNode = oldTextNode.splitText(1);
if (useRangeBounds){
// getBoundingClientRect is supported for ranges
if (document.createRange){
var range = document.createRange();
range.selectNode(oldTextNode);
}else{
// TODO add IE support
var range = document.body.createTextRange();
}
if (range.getBoundingClientRect()){
var bounds = range.getBoundingClientRect();
}else{
var bounds = {};
}
}else{
// it isn't supported, so let's wrap it inside an element instead and the bounds there
var parent = oldTextNode.parentNode;
var wrapElement = document.createElement('wrapper');
var backupText = oldTextNode.cloneNode(true);
wrapElement.appendChild(oldTextNode.cloneNode(true));
parent.replaceChild(wrapElement,oldTextNode);
var bounds = getBounds(wrapElement);
parent.replaceChild(backupText,wrapElement);
}
printText(oldTextNode.nodeValue,bounds.left,bounds.bottom);
switch(text_decoration) {
case "underline":
// guesstimate the y-position of the line
// TODO try and find a more accurate way to find the baseline of the text
newRect(bounds.left,Math.round(bounds.bottom-(bounds.height/7)),bounds.width,1,color);
break;
case "overline":
newRect(bounds.left,bounds.top,bounds.width,1,color);
break;
case "line-through":
// TODO try and find exact position for line-through
newRect(bounds.left,Math.round(bounds.top+(bounds.height/2)),bounds.width,1,color);
break;
}
oldTextNode = newTextNode;
}
}
}
/*
* Function to apply text-transform attribute to text
*/
function textTransform(text,transform){
switch(transform){
case "lowercase":
return text.toLowerCase();
break;
case "capitalize":
return text.replace( /(^|\s|:|-|\(|\))([a-z])/g , function(m,p1,p2){
return p1+p2.toUpperCase();
} );
break;
case "uppercase":
return text.toUpperCase();
break;
default:
return text;
}
}
/*
* Finished rendering, send callback
*/
function finish(){
log("Finished rendering");
if (opts.renderViewport){
// let's crop it to viewport only then
var newCanvas = document.createElement('canvas');
var newctx = newCanvas.getContext('2d');
newCanvas.width = window.innerWidth;
newCanvas.height = window.innerHeight;
}
opts.ready(canvas);
}
/*
* Function for looping through array
*/
function each(arrayLoop,callbackFunc){
callbackFunc = callbackFunc || function(){};
for (var i=0;i<arrayLoop.length;i++){
callbackFunc(i,arrayLoop[i]);
}
}
/*
* Function to extend object
*/
function extendObj(options,defaults){
for (var key in options){
defaults[key] = options[key];
}
return defaults;
}
/*
*Function to trim whitespace from text
*/
function trim(text) {
return text.replace(/^\s*/, "").replace(/\s*$/, "");
}
/*
* Get element childNodes
*/
function getContents(el){
return (el.nodeName == "iframe" ) ?
el.contentDocument || el.contentWindow.document :
el.childNodes;
}
// Start script
init();
}

21
html2canvas.min.js vendored Normal file
View File

@ -0,0 +1,21 @@
/*
* html2canvas v0.11 <http://html2canvas.hertzen.com>
*
* Copyright 2011, Niklas von Hertzen <http://hertzen.com>
* http://www.twitter.com/niklasvh
*
* Released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
function html2canvas(s,I){function t(){if(j.length==0||u==j.length/2)m("Started parsing"),x(s),J(s)}function m(a){q.logging&&(typeof console!="undefined"&&console.log?console.log(a):alert(a))}function y(a){if(j.indexOf(a)==-1){j.push(a);var b=new Image;$(b).load(function(){u++;t()});b.onerror=function(){j.splice(j.indexOf(b.src),2);u++;t()};b.src=a;j.push(b)}}function z(a){n($(a).contents(),function(a,e){RegExp("("+A+")").test(e.nodeName)||z(e)});if(a.nodeType==1||typeof a.nodeType=="undefined")if((a=
i(a,"background-image"))&&a!="1"&&a!="none"&&a.substring(0,7)!="-webkit")a=B(a),y(a)}function v(a){if(!RegExp("("+A+")").test(a.nodeName)){x(a);var b=$(a).contents();b.length==1?b[0].nodeType==1?v(b[0]):b[0].nodeType==3&&C(a,b[0]):n(b,function(b,g){g.nodeType==1?v(g):g.nodeType==3&&C(a,g)})}}function J(a){n(a.children,function(a,e){v(e)});K()}function B(a){a.substr(0,5)=='url("'?(a=a.substr(5),a=a.substr(0,a.length-2)):(a=a.substr(4),a=a.substr(0,a.length-1));return a}function D(a){a=j.indexOf(a);
return a!=-1?j[a+1]:!1}function E(a){window.scroll(0,0);if(a.getBoundingClientRect)return a=a.getBoundingClientRect(),a.top=a.top,a.left=a.left,a;else{var b=$(a).offset();return{left:b.left+parseInt(i(a,"border-left-width"),10),top:b.top+parseInt(i(a,"border-top-width"),10),width:$(a).innerWidth(),height:$(a).innerHeight()}}}function x(a){var b=E(a),e=b.left,g=b.top,f=b.width,d=b.height,b=i(a,"background-color"),c=L(a);n(c,function(a,b){if(b.width>0){var h=e,i=g,j=f,k=d-c[2].width;switch(a){case 0:k=
c[0].width;break;case 1:h=e+f-c[1].width;j=c[1].width;break;case 2:i=i+d-c[2].width;k=c[2].width;break;case 3:j=c[3].width}r(h,i,j,k,b.color)}});r(e+c[3].width,g+c[0].width,f-(c[1].width+c[3].width),d-(c[0].width+c[2].width),b);M(a,{left:e+c[3].width,top:g+c[0].width,width:f-(c[1].width+c[3].width),height:d-(c[0].width+c[2].width)});a.nodeName=="IMG"&&((F=D(a.getAttribute("src")))?k.drawImage(F,e+parseInt(i(a,"padding-left"),10),g+parseInt(i(a,"padding-top"),10)):m("Error loading <img>:"+a.getAttribute("src")))}
function M(a,b){var e=i(a,"background-image"),g=i(a,"background-repeat");if(typeof e!="undefined"&&/^(1|none)$/.test(e)==!1){var e=B(e),f=D(e),d,c=i(a,"background-position").split(" "),o;c[0].indexOf("%")!=-1?(o=parseFloat(c[0])/100,d=b.width*o-f.width*o):d=parseInt(c[0],10);c[1].indexOf("%")!=-1?(o=parseFloat(c[1])/100,c=b.height*o-f.height*o):c=parseInt(c[1],10);d={top:c,left:d};if(f)switch(g){case "repeat-x":G(f,d,b.left,b.top,b.width,b.height);break;case "repeat-y":var e=b.left,g=b.top,c=b.height,
j=Math.min(f.width,b.width);d.top-=Math.ceil(d.top/f.height)*f.height;for(h=g+d.top;h<=c+g;)o=Math.floor(h+f.height)>c+g?c+g-h:f.height,w(f,e+d.left,h,j,o,e,g),h=Math.floor(h+f.height);break;case "no-repeat":w(f,d.left+b.left,d.top+b.top,Math.min(b.width,f.width),Math.min(b.height,f.height),b.left,b.top);break;default:d.top-=Math.ceil(d.top/f.height)*f.height;for(h=b.top+d.top;h<=b.height+b.top;)e=Math.min(f.height,b.height+b.top-h),e=Math.floor(h+f.height)>e+h?e+h-h:f.height,h<b.top?(g=b.top-h,h=
b.top):g=0,G(f,d,b.left,h,b.width,e),g>0&&(d.top+=g),h=Math.floor(h+f.height)-g}else m("Error loading background:"+e)}}function G(a,b,e,g,f,d){var d=Math.min(a.height,d),c;b.left-=Math.ceil(b.left/a.width)*a.width;for(l=e+b.left;l<=f+e;)c=Math.floor(l+a.width)>f+e?f+e-l:a.width,w(a,l,g+b.top,c,d,e,g),l=Math.floor(l+a.width)}function w(a,b,e,g,f,d,c){var h=0,i=0;d-b>0&&(h=d-b);c-e>0&&(i=c-e);k.drawImage(a,h,i,g-h,f-i,b+h,e+i,g-h,f-i)}function L(a){var b=[];n(["top","right","bottom","left"],function(e,
g){b.push({width:parseInt(i(a,"border-"+g+"-width"),10),color:i(a,"border-"+g+"-color")})});return b}function r(a,b,e,g,f){if(f!="transparent")k.fillStyle=f,k.fillRect(a,b,e,g)}function i(a,b){return $(a).css(b)}function C(a,b){var e=i(a,"font-family"),g=i(a,"font-size"),f=i(a,"color"),d=i(a,"font-weight"),c=i(a,"font-style"),h=i(a,"text-decoration");b.nodeValue=N(b.nodeValue,i(a,"text-transform"));var j=b.nodeValue;if(j.length>0){switch(d){case "401":d="bold"}k.font=d+" "+c+" "+g+" "+e;k.fillStyle=
f;c=b;for(e=0;e<j.length;e++){g=c.splitText(1);if(H)document.createRange?(d=document.createRange(),d.selectNode(c)):d=document.body.createTextRange(),d=d.getBoundingClientRect()?d.getBoundingClientRect():{};else{var m=c.parentNode,l=document.createElement("wrapper"),n=c.cloneNode(!0);l.appendChild(c.cloneNode(!0));m.replaceChild(l,c);d=E(l);m.replaceChild(n,l)}c=c.nodeValue;m=d.left;l=d.bottom;c.replace(/^\s*/,"").replace(/\s*$/,"").length>0&&k.fillText(c,m,l);switch(h){case "underline":r(d.left,
Math.round(d.bottom-d.height/7),d.width,1,f);break;case "overline":r(d.left,d.top,d.width,1,f);break;case "line-through":r(d.left,Math.round(d.top+d.height/2),d.width,1,f)}c=g}}}function N(a,b){switch(b){case "lowercase":return a.toLowerCase();case "capitalize":return a.replace(/(^|\s|:|-|\(|\))([a-z])/g,function(a,b,f){return b+f.toUpperCase()});case "uppercase":return a.toUpperCase();default:return a}}function K(){m("Finished rendering");if(q.renderViewport){var a=document.createElement("canvas");
a.getContext("2d");a.width=window.innerWidth;a.height=window.innerHeight}q.ready(p)}function n(a,b){for(var b=b||function(){},e=0;e<a.length;e++)b(e,a[e])}var q={logging:!1,ready:function(a){document.body.appendChild(a)},renderViewport:!0},q=function(a,b){for(var e in a)b[e]=a[e];return b}(I||{},q),u=0,j=[],p,k,l,h,F,A="IFRAME|OBJECT|PARAM",H=!1;if(document.createRange)var O=document.createRange(),H=new Boolean(O.getBoundingClientRect);(function(){p=document.createElement("canvas");p.width=$(document).width();
p.height=$(document).height()+10;p.getContext&&(k=p.getContext("2d"));k?(k.textBaseline="bottom",m("Finding background images"),z(s),m("Finding images"),n(document.images,function(a,b){y(b.getAttribute("src"))}),j.length==0&&t()):m("Canvas not available")})()};

View File

@ -0,0 +1,70 @@
/*
* @author Niklas von Hertzen <niklas at hertzen.com>
* @created 16.7.2011
* @website http://hertzen.com
*/
/*
* jQuery helper plugin for examples and tests
*/
(function( $ ){
$.fn.html2canvas = function() {
var message,
timer;
html2canvas(this.get(0),{
ready:function(canvas){
document.body.appendChild(canvas);
var canvas = $(canvas);
canvas.css('position','absolute')
.css('left',0).css('top',0);
// $('body').append(canvas);
$(canvas).siblings().toggle();
$(window).click(function(){
if (!canvas.is(':visible')){
$(canvas).toggle().siblings().toggle();
throwMessage("Canvas Render visible");
} else{
$(canvas).siblings().toggle();
$(canvas).toggle();
throwMessage("Canvas Render hidden");
}
});
}
});
function throwMessage(msg){
window.clearTimeout(timer);
timer = window.setTimeout(function(){
message.fadeOut(function(){
message.remove();
});
},2000);
$(message).remove();
message = $('<div />').text(msg).css({
margin:0,
padding:10,
background: "#000",
opacity:0.7,
position:"fixed",
top:10,
right:10,
fontFamily: 'Tahoma' ,
color:'#fff',
fontSize:12,
borderRadius:12,
width:'auto',
height:'auto'
}).hide().fadeIn().appendTo('body');
}
};
})( jQuery );

90
tests/background.html Normal file
View File

@ -0,0 +1,90 @@
<!--
* @author Niklas von Hertzen <niklas at hertzen.com>
* @created 15.7.2011
* @website http://hertzen.com
-->
<!DOCTYPE html>
<html>
<head>
<title>Background attribute tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="#" type="text/css" rel="stylesheet">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript" src="../html2canvas.min.js"></script>
<script type="text/javascript" src="../jquery.plugin.html2canvas.js"></script>
<script type="text/javascript">
$(window).ready(function() {
$('body').html2canvas();
});
</script>
<style>
.small div{
width:100px;
height:100px;
float:left;
margin:10px;
border:1px solid #000;
}
.medium div{
width:200px;
height:200px;
float:left;
margin:10px;
border:1px solid #000;
}
.small, .medium{
clear:both;
}
div{
display:block;
}
</style>
</head>
<body>
<div class="medium">
<div style="background:url(image.jpg);"></div>
<div style="background:url(image.jpg) repeat-x;"></div>
<div style="background:url(image.jpg) repeat-y;"></div>
<div style="background:url(image.jpg) no-repeat;"></div>
</div>
<div class="small">
<div style="background:url(image.jpg);"></div>
<div style="background:url(image.jpg) repeat-x;"></div>
<div style="background:url(image.jpg) repeat-y;"></div>
<div style="background:url(image.jpg) no-repeat;"></div>
</div>
<div class="medium">
<div style="background:url(image.jpg) center center;"></div>
<div style="background:url(image.jpg) repeat-x center center;"></div>
<div style="background:url(image.jpg) repeat-y center center;"></div>
<div style="background:url(image.jpg) no-repeat center center;"></div>
</div>
<div class="small">
<div style="background:url(image.jpg) center center;"></div>
<div style="background:url(image.jpg) repeat-x center center;"></div>
<div style="background:url(image.jpg) repeat-y center center;"></div>
<div style="background:url(image.jpg) no-repeat center center;"></div>
</div>
<div class="medium">
<div style="background:url(image.jpg) 50px 50px;"></div>
<div style="background:url(image.jpg) repeat-x 50px 50px;"></div>
<div style="background:url(image.jpg) repeat-y 50px 50px;"></div>
<div style="background:url(image.jpg) no-repeat 50px 50px;"></div>
</div>
</body>
</html>

BIN
tests/image.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

129
tests/text.html Normal file
View File

@ -0,0 +1,129 @@
<!--
* @author Niklas von Hertzen <niklas at hertzen.com>
* @created 16.7.2011
* @website http://hertzen.com
-->
<!DOCTYPE html>
<html>
<head>
<title>Text tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="#" type="text/css" rel="stylesheet">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript" src="../html2canvas.js"></script>
<script type="text/javascript" src="../jquery.plugin.html2canvas.js"></script>
<script type="text/javascript">
$(window).ready(function() {
$('body').html2canvas();
});
</script>
<style>
.small{
font-size:14px;
}
.medium{
font-size:18px;
}
.large{
font-size:24px;
}
div{
float:left;
}
h2 {
clear:both;
}
</style>
</head>
<body> <h1>&lt;h1&gt; text-decoration</h1>
<div style="font-family:Arial;">
<h2>Arial</h2>
<ol class="small">
<li style="text-decoration:none;">text-decoration:none;</li>
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
<ol class="medium">
<li style="text-decoration:none;">text-decoration:none;</li>
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
<ol class="large">
<li style="text-decoration:none;">text-decoration:none;</li>
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
</div>
<div style="font-family:Verdana;">
<h2>Verdana</h2>
<ol class="small">
<li style="text-decoration:none;">text-decoration:none;</li>
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
<ol class="medium">
<li style="text-decoration:none;">text-decoration:none;</li>
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
<ol class="large">
<li style="text-decoration:none;">text-decoration:none;</li>
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
</div>
<div style="font-family:Tahoma;">
<h2>Tahoma</h2>
<ol class="small">
<li style="text-decoration:none;">text-decoration:none;</li>
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
<ol class="medium">
<li style="text-decoration:none;">text-decoration:none;</li>
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
<ol class="large">
<li style="text-decoration:none;">text-decoration:none;</li>
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
</div>
<h2>&lt;h2&gt; text-transform</h2>
<ul>
<li style="text-transform:none;">text-transform:none;</li>
<li style="text-transform:capitalize;">text-transform:capitalize; (including foreign characters such as Öaäå)</li>
<li style="text-transform:uppercase;">text-transform:uppercase;</li>
<li style="text-transform:lowercase;">text-transform:lowercase;</li>
</ul>
<h3>&lt;h3&gt; misc text alignments</h3>
<ul>
<li style="word-spacing:5px;">word-spacing:5px; (as each letter is rendered individually, the bounds will always be correct)</li>
<li style="line-height:35px;">line-height:35px; <br />(same goes for line-height)</li>
<li style="letter-spacing:5px;">letter-spacing:5px;</li>
<li style="text-align:right;width:300px;">text-align:right;width:300px;</li>
<li style="font-variant:small-caps;">font-variant:small-caps; (not yet supported)</li>
</ul>
</body>
</html>