added support for CORS images and option to create canvas as tainted

This commit is contained in:
Niklas von Hertzen 2012-03-01 19:44:25 +02:00
parent c86d12b915
commit 3ad49efa00
5 changed files with 65 additions and 33 deletions

View File

@ -38,7 +38,7 @@ For more information and examples, please visit the <a href="http://html2canvas.
### Changelog ###
v0.33 -
* Added support for CORS images and option to create canvas as tainted (<a href="#">niklasvh</a>)
* Improved minification saved ~1K! (<a href="https://github.com/cobexer/html2canvas/commit/b82be022b2b9240bd503e078ac980bde2b953e43">cobexer</a>)
* Added integrated support for Flashcanvas (<a href="https://github.com/niklasvh/html2canvas/commit/e9257191519f67d74fd5e364d8dee3c0963ba5fc">niklasvh</a>)
* Fixed a variety of legacy IE bugs (<a href="https://github.com/niklasvh/html2canvas/commit/b65357c55d0701017bafcd357bc654b54d458f8f">niklasvh</a>)

View File

@ -10,7 +10,9 @@ html2canvas.Preload = function(element, opts){
var options = {
proxy: "http://html2canvas.appspot.com/",
timeout: 0 // no timeout
timeout: 0, // no timeout
useCORS: false, // try to load images as CORS (where available), before falling back to proxy
allowTaint: false // whether to allow images to taint the canvas, won't need proxy if set to true
},
images = {
numLoaded: 0, // also failed are counted here
@ -26,6 +28,9 @@ html2canvas.Preload = function(element, opts){
domImages = doc.images, // TODO probably should limit it to images present in the element only
imgLen = domImages.length,
link = doc.createElement("a"),
supportCORS = (function( img ){
return (img.crossOrigin !== undefined);
})(new Image()),
timeoutTimer;
link.href = window.location.href;
@ -41,7 +46,7 @@ html2canvas.Preload = function(element, opts){
function isSameOrigin(url){
link.href = url;
var origin = link.protocol + link.host;
return ":" === origin || (origin === pageOrigin);
return (origin === pageOrigin);
}
function start(){
@ -215,36 +220,78 @@ html2canvas.Preload = function(element, opts){
function setImageLoadHandlers(img, imageObj) {
img.onload = function() {
if ( imageObj.timer !== undefined ) {
// CORS succeeded
window.clearTimeout( imageObj.timer );
}
images.numLoaded++;
imageObj.succeeded = true;
start();
};
img.onerror = function() {
if (img.crossOrigin === "anonymous") {
// CORS failed
window.clearTimeout( imageObj.timer );
// let's try with proxy instead
if ( options.proxy ) {
var src = img.src;
img = new Image();
imageObj.img = img;
img.src = src;
proxyGetImage( img.src, img, imageObj );
return;
}
}
images.numLoaded++;
images.numFailed++;
imageObj.succeeded = false;
start();
};
}
// work around for https://bugs.webkit.org/show_bug.cgi?id=80028
function isComplete() {
if (!this.img.complete) {
this.timer = window.setTimeout(this.img.customComplete, 100)
} else {
this.img.onerror();
}
}
methods = {
loadImage: function( src ) {
var img, imageObj;
var img, imageObj;
if ( src && images[src] === undefined ) {
img = new Image();
img = new Image();
if ( src.match(/data:image\/.*;base64,/i) ) {
img.src = src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, '');
imageObj = images[src] = { img: img };
images.numTotal++;
setImageLoadHandlers(img, imageObj);
}
else if ( isSameOrigin( src ) ) {
} else if ( isSameOrigin( src ) || options.allowTaint === true ) {
imageObj = images[src] = { img: img };
images.numTotal++;
setImageLoadHandlers(img, imageObj);
img.src = src;
}
else if ( options.proxy ) {
} else if ( supportCORS && !options.allowTaint && options.useCORS ) {
// attempt to load with CORS
img.crossOrigin = "anonymous";
imageObj = images[src] = { img: img };
images.numTotal++;
setImageLoadHandlers(img, imageObj);
img.src = src;
img.customComplete = isComplete.bind(imageObj);
img.customComplete();
} else if ( options.proxy ) {
imageObj = images[src] = { img: img };
images.numTotal++;
proxyGetImage( src, img, imageObj );

View File

@ -127,35 +127,16 @@ html2canvas.Renderer = function(parseQueue, opts){
if (renderItem.name === "fillRect") {
if (!usingFlashcanvas || renderItem['arguments'][0] + renderItem['arguments'][2] < flashMaxSize && renderItem['arguments'][1] + renderItem['arguments'][3] < flashMaxSize) {
ctx.fillRect(
renderItem['arguments'][0],
renderItem['arguments'][1],
renderItem['arguments'][2],
renderItem['arguments'][3]
);
ctx.fillRect.apply( ctx, renderItem['arguments'] );
}
}else if(renderItem.name === "fillText") {
if (!usingFlashcanvas || renderItem['arguments'][1] < flashMaxSize && renderItem['arguments'][2] < flashMaxSize) {
ctx.fillText(
renderItem['arguments'][0],
renderItem['arguments'][1],
renderItem['arguments'][2]
);
ctx.fillText.apply( ctx, renderItem['arguments'] );
}
}else if(renderItem.name === "drawImage") {
if (renderItem['arguments'][8] > 0 && renderItem['arguments'][7]){
ctx.drawImage(
renderItem['arguments'][0],
renderItem['arguments'][1],
renderItem['arguments'][2],
renderItem['arguments'][3],
renderItem['arguments'][4],
renderItem['arguments'][5],
renderItem['arguments'][6],
renderItem['arguments'][7],
renderItem['arguments'][8]
);
ctx.drawImage.apply( ctx, renderItem['arguments'] );
}
}

View File

@ -5,7 +5,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="test.js"></script>
<base href="http://www.google.com/" />
<base href="http://www.google.com/" />
</head>
<body>
<h1>External image</h1>
@ -14,5 +14,8 @@
<h1>External image (using &lt;base&gt; href)</h1>
<img src="/logos/2011/gregormendel11-res.jpg" />
<h1>External image (CORS)</h1>
<img src="http://publishmydata.com/assets/home/blue_bg.png" />
</body>
</html>

View File

@ -19,7 +19,8 @@
setTimeout(function() {
$(document.body).html2canvas({
logging: true,
profile: true
profile: true,
useCORS: true
});
}, 100);
};