mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
rewrote image handling from using an array to an object
The image loading done in Preload.js used an array to store image src and image object as 2 consecutive entries in that array. Using the src as an index in a hash allows direct instead of a linear search and also allows to store more data. * improved cleanup of images loaded with the proxy * this also adds a timeout for the image loading phase, after that running image requests are aborted and the rendering is started
This commit is contained in:
parent
2a3d6a0a35
commit
73763c8114
36
src/Parse.js
36
src/Parse.js
@ -48,7 +48,7 @@ html2canvas.Parse = function (element, images, opts) {
|
||||
childrenLen;
|
||||
|
||||
|
||||
images = images || [];
|
||||
images = images || {};
|
||||
|
||||
// Test whether we can use ranges to measure bounding boxes
|
||||
// Opera doesn't provide valid bounds.height/bottom even though it supports the method.
|
||||
@ -515,27 +515,12 @@ html2canvas.Parse = function (element, images, opts) {
|
||||
}
|
||||
|
||||
function loadImage (src){
|
||||
|
||||
var imgIndex = -1,
|
||||
i,
|
||||
imgLen;
|
||||
if (images.indexOf){
|
||||
imgIndex = images.indexOf(src);
|
||||
}else{
|
||||
for(i = 0, imgLen = images.length; i < imgLen.length; i+=1){
|
||||
if(images[i] === src) {
|
||||
imgIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (imgIndex > -1){
|
||||
return images[imgIndex+1];
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
|
||||
var img = images[src];
|
||||
if (img && img.succeeded === true) {
|
||||
return img.img;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1004,8 +989,7 @@ html2canvas.Parse = function (element, images, opts) {
|
||||
|
||||
}
|
||||
}else{
|
||||
|
||||
html2canvas.log("Error loading background:" + background_image);
|
||||
html2canvas.log("html2canvas: Error loading background:" + background_image);
|
||||
//console.log(images);
|
||||
}
|
||||
|
||||
@ -1164,8 +1148,8 @@ html2canvas.Parse = function (element, images, opts) {
|
||||
bounds.height - (borders[0].width + borders[2].width + paddingTop + paddingBottom) //dh
|
||||
);
|
||||
|
||||
}else {
|
||||
html2canvas.log("Error loading <img>:" + imgSrc);
|
||||
}else{
|
||||
html2canvas.log("html2canvas: Error loading <img>:" + imgSrc);
|
||||
}
|
||||
break;
|
||||
case "INPUT":
|
||||
|
162
src/Preload.js
162
src/Preload.js
@ -9,11 +9,16 @@
|
||||
html2canvas.Preload = function(element, opts){
|
||||
|
||||
var options = {
|
||||
"proxy": "http://html2canvas.appspot.com/"
|
||||
proxy: "http://html2canvas.appspot.com/",
|
||||
timeout: 0 // no timeout
|
||||
},
|
||||
images = {
|
||||
numLoaded: 0, // also failed are counted here
|
||||
numFailed: 0,
|
||||
numTotal: 0,
|
||||
cleanupDone: false
|
||||
},
|
||||
images = [],
|
||||
pageOrigin = window.location.protocol + window.location.host,
|
||||
imagesLoaded = 0,
|
||||
methods,
|
||||
i,
|
||||
count = 0,
|
||||
@ -36,24 +41,9 @@ html2canvas.Preload = function(element, opts){
|
||||
|
||||
}
|
||||
|
||||
function getIndex(array,src){
|
||||
var i, arrLen;
|
||||
if (array.indexOf){
|
||||
return array.indexOf(src);
|
||||
}else{
|
||||
for(i = 0, arrLen = array.length; i < arrLen; i+=1){
|
||||
if(this[i] === src) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function start(){
|
||||
if (images.length === 0 || imagesLoaded === images.length/2){
|
||||
|
||||
html2canvas.log("html2canvas: start: images: " + images.numLoaded + " / " + images.numTotal + " (failed: " + images.numFailed + ")");
|
||||
if (!images.firstRun && images.numLoaded >= images.numTotal){
|
||||
|
||||
/*
|
||||
this.log('Finished loading '+this.imagesLoaded+' images, Started parsing');
|
||||
@ -63,20 +53,22 @@ html2canvas.Preload = function(element, opts){
|
||||
if (typeof options.complete === "function"){
|
||||
options.complete(images);
|
||||
}
|
||||
|
||||
html2canvas.log("Finished loading images: # " + images.numTotal + " (failed: " + images.numFailed + ")");
|
||||
}
|
||||
}
|
||||
|
||||
function proxyGetImage(url, img){
|
||||
var callback_name,
|
||||
scriptUrl = options.proxy,
|
||||
script,
|
||||
imgObj = images[url];
|
||||
|
||||
link.href = url;
|
||||
url = link.href; // work around for pages with base href="" set
|
||||
var callback_name,
|
||||
scriptUrl = options.proxy,
|
||||
script;
|
||||
url = link.href; // work around for pages with base href="" set - WARNING: this may change the url -> so access imgObj from images map before changing that url!
|
||||
|
||||
callback_name = 'html2canvas_' + count;
|
||||
|
||||
|
||||
imgObj.callbackname = callback_name;
|
||||
|
||||
if (scriptUrl.indexOf("?") > -1) {
|
||||
scriptUrl += "&";
|
||||
@ -87,17 +79,25 @@ html2canvas.Preload = function(element, opts){
|
||||
|
||||
window[callback_name] = function(a){
|
||||
if (a.substring(0,6) === "error:"){
|
||||
images.splice(getIndex(images, url), 2);
|
||||
imgObj.succeeded = false;
|
||||
images.numLoaded++;
|
||||
images.numFailed++;
|
||||
start();
|
||||
}else{
|
||||
} else {
|
||||
img.onload = function(){
|
||||
imagesLoaded+=1;
|
||||
imgObj.succeeded = true;
|
||||
images.numLoaded++;
|
||||
start();
|
||||
};
|
||||
|
||||
img.src = a;
|
||||
}
|
||||
delete window[callback_name];
|
||||
window[callback_name] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)
|
||||
try {
|
||||
delete window[callback_name]; // for all browser that support this
|
||||
} catch(ex) {}
|
||||
script.parentNode.removeChild(script);
|
||||
script = null;
|
||||
imgObj.callbackname = undefined;
|
||||
};
|
||||
|
||||
count += 1;
|
||||
@ -105,6 +105,7 @@ html2canvas.Preload = function(element, opts){
|
||||
script = doc.createElement("script");
|
||||
script.setAttribute("src", scriptUrl);
|
||||
script.setAttribute("type", "text/javascript");
|
||||
imgObj.script = script;
|
||||
window.document.body.appendChild(script);
|
||||
|
||||
/*
|
||||
@ -180,9 +181,9 @@ html2canvas.Preload = function(element, opts){
|
||||
img = html2canvas.Generate.Gradient( background_image, html2canvas.Util.Bounds( el ) );
|
||||
|
||||
if ( img !== undefined ){
|
||||
images.push(background_image);
|
||||
images.push(img);
|
||||
imagesLoaded++;
|
||||
images[background_image] = { img: img, succeeded: true };
|
||||
images.numTotal++;
|
||||
images.numLoaded++;
|
||||
start();
|
||||
|
||||
}
|
||||
@ -204,58 +205,110 @@ html2canvas.Preload = function(element, opts){
|
||||
methods = {
|
||||
loadImage: function( src ) {
|
||||
var img;
|
||||
if ( getIndex(images, src) === -1 ) {
|
||||
if ( images[src] === undefined ) {
|
||||
if ( src.match(/data:image\/.*;base64,/i) ) {
|
||||
|
||||
//Base64 src
|
||||
img = new Image();
|
||||
img.src = src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, '');
|
||||
|
||||
images.push( src );
|
||||
images.push( img );
|
||||
|
||||
imagesLoaded+=1;
|
||||
images[src] = { img: img, succeeded: true };
|
||||
images.numTotal++;
|
||||
images.numLoaded++;
|
||||
start();
|
||||
|
||||
}else if ( isSameOrigin( src ) ) {
|
||||
|
||||
images.push( src );
|
||||
img = new Image();
|
||||
images[src] = { img: img };
|
||||
images.numTotal++;
|
||||
|
||||
img.onload = function() {
|
||||
imagesLoaded+=1;
|
||||
images.numLoaded++;
|
||||
images[src].succeeded = true;
|
||||
start();
|
||||
|
||||
};
|
||||
|
||||
img.onerror = function() {
|
||||
images.splice( getIndex( images, img.src ), 2 );
|
||||
images.numLoaded++;
|
||||
images.numFailed++;
|
||||
images[src].succeeded = false;
|
||||
start();
|
||||
};
|
||||
|
||||
img.src = src;
|
||||
images.push(img);
|
||||
|
||||
}else if ( options.proxy ){
|
||||
// console.log('b'+src);
|
||||
images.push( src );
|
||||
img = new Image();
|
||||
images[src] = { img: img };
|
||||
images.numTotal++;
|
||||
proxyGetImage( src, img );
|
||||
images.push( img );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
cleanupDOM: function(cause) {
|
||||
var img;
|
||||
if (!images.cleanupDone) {
|
||||
if (cause && typeof cause === "string") {
|
||||
html2canvas.log("html2canvas: Cleanup because: " + cause);
|
||||
} else {
|
||||
html2canvas.log("html2canvas: Cleanup after timeout: " + options.timeout + " ms.");
|
||||
}
|
||||
|
||||
for (src in images) {
|
||||
if (images.hasOwnProperty(src)) {
|
||||
img = images[src];
|
||||
if (typeof img === "object" && img.callbackname && img.succeeded === undefined) {
|
||||
// cancel proxy image request
|
||||
window[img.callbackname] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)
|
||||
try {
|
||||
delete window[img.callbackname]; // for all browser that support this
|
||||
} catch(ex) {}
|
||||
if (img.script && img.script.parentNode) {
|
||||
img.script.setAttribute("src", "about:blank"); // try to cancel running request
|
||||
img.script.parentNode.removeChild(img.script);
|
||||
}
|
||||
images.numLoaded++;
|
||||
images.numFailed++;
|
||||
html2canvas.log("html2canvas: Cleaned up failed img: '" + src + "' Steps: " + images.numLoaded + " / " + images.numTotal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cancel any pending requests
|
||||
if(window.stop !== undefined) {
|
||||
window.stop();
|
||||
} else if(document.execCommand !== undefined) {
|
||||
document.execCommand("Stop", false);
|
||||
}
|
||||
if (document.close !== undefined) {
|
||||
document.close();
|
||||
}
|
||||
images.cleanupDone = true;
|
||||
if (!(cause && typeof cause === "string")) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
},
|
||||
renderingDone: function() {
|
||||
if (timeoutTimer) {
|
||||
window.clearTimeout(timeoutTimer);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// add something to array
|
||||
images.push('start');
|
||||
if (options.timeout > 0) {
|
||||
timeoutTimer = window.setTimeout(methods.cleanupDOM, options.timeout);
|
||||
}
|
||||
var startTime = (new Date()).getTime();
|
||||
this.log('html2canvas: Preload starts: finding background-images');
|
||||
images.firstRun = true;
|
||||
|
||||
getImages( element );
|
||||
|
||||
|
||||
this.log('html2canvas: Preload: Finding images');
|
||||
// load <img> images
|
||||
for (i = 0; i < imgLen; i+=1){
|
||||
var imgSrc = domImages[i].getAttribute( "src" );
|
||||
@ -264,10 +317,9 @@ html2canvas.Preload = function(element, opts){
|
||||
}
|
||||
}
|
||||
|
||||
// remove 'start'
|
||||
images.splice(0, 1);
|
||||
|
||||
if ( images.length === 0 ) {
|
||||
images.firstRun = false;
|
||||
this.log('html2canvas: Preload: Done.');
|
||||
if ( images.numTotal === images.numLoaded ) {
|
||||
start();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user