mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
Make image loading to work on top of Promises/polyfill
This commit is contained in:
parent
355bde3655
commit
9754c224e5
@ -13,5 +13,6 @@
|
|||||||
"globals": {
|
"globals": {
|
||||||
"jQuery": true
|
"jQuery": true
|
||||||
},
|
},
|
||||||
"predef": ["NodeContainer", "StackingContext", "TextContainer", "CanvasRenderer", "Renderer", "Support"]
|
"predef": ["NodeContainer", "StackingContext", "TextContainer", "ImageLoader", "CanvasRenderer", "Renderer", "Support", "bind", "Promise",
|
||||||
|
"ImageContainer", "ProxyImageContainer", "DummyImageContainer"]
|
||||||
}
|
}
|
||||||
|
11
Gruntfile.js
11
Gruntfile.js
@ -21,16 +21,7 @@ module.exports = function(grunt) {
|
|||||||
concat: {
|
concat: {
|
||||||
dist: {
|
dist: {
|
||||||
src: [
|
src: [
|
||||||
'src/Core.js',
|
'src/**/*.js'
|
||||||
'src/Font.js',
|
|
||||||
'src/Generate.js',
|
|
||||||
'src/Queue.js',
|
|
||||||
'src/Parse.js',
|
|
||||||
'src/Preload.js',
|
|
||||||
'src/Renderer.js',
|
|
||||||
'src/Support.js',
|
|
||||||
'src/Util.js',
|
|
||||||
'src/renderers/Canvas.js'
|
|
||||||
],
|
],
|
||||||
dest: 'build/<%= pkg.name %>.js'
|
dest: 'build/<%= pkg.name %>.js'
|
||||||
},
|
},
|
||||||
|
13
src/core.js
13
src/core.js
@ -34,13 +34,16 @@ function NodeParser(element, renderer, options) {
|
|||||||
this.range = null;
|
this.range = null;
|
||||||
this.stack = new StackingContext(true, 1, element.ownerDocument, null);
|
this.stack = new StackingContext(true, 1, element.ownerDocument, null);
|
||||||
var parent = new NodeContainer(element, null);
|
var parent = new NodeContainer(element, null);
|
||||||
parent.blockFormattingContext = parent;
|
|
||||||
this.nodes = [parent].concat(this.getChildren(parent)).filter(function(container) {
|
this.nodes = [parent].concat(this.getChildren(parent)).filter(function(container) {
|
||||||
return container.visible = container.isElementVisible();
|
return container.visible = container.isElementVisible();
|
||||||
});
|
});
|
||||||
|
this.imageLoader = new ImageLoader(this.nodes.filter(isElement), options, this.support);
|
||||||
this.createStackingContexts();
|
this.createStackingContexts();
|
||||||
this.sortStackingContexts(this.stack);
|
this.sortStackingContexts(this.stack);
|
||||||
this.parse(this.stack);
|
|
||||||
|
this.imageLoader.ready.then(bind(function() {
|
||||||
|
this.parse(this.stack);
|
||||||
|
}, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeParser.prototype.getChildren = function(parentContainer) {
|
NodeParser.prototype.getChildren = function(parentContainer) {
|
||||||
@ -518,3 +521,9 @@ function zIndexSort(a, b) {
|
|||||||
function hasOpacity(container) {
|
function hasOpacity(container) {
|
||||||
return container.css("opacity") < 1;
|
return container.css("opacity") < 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bind(callback, context) {
|
||||||
|
return function() {
|
||||||
|
return callback.apply(context, arguments);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
14
src/imagecontainer.js
Normal file
14
src/imagecontainer.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
function ImageContainer(src, cors) {
|
||||||
|
this.src = src;
|
||||||
|
this.image = new Image();
|
||||||
|
var image = this.image;
|
||||||
|
this.promise = new Promise(function(resolve, reject) {
|
||||||
|
image.onload = resolve;
|
||||||
|
image.onerror = reject;
|
||||||
|
if (cors) {
|
||||||
|
image.crossOrigin = "anonymous";
|
||||||
|
}
|
||||||
|
image.src = src;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
56
src/imageloader.js
Normal file
56
src/imageloader.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
function ImageLoader(nodes, options, support) {
|
||||||
|
this.link = null;
|
||||||
|
this.options = options;
|
||||||
|
this.support = support;
|
||||||
|
this.origin = window.location.protocol + window.location.host;
|
||||||
|
this.images = nodes.reduce(bind(this.findImages, this), []);
|
||||||
|
this.ready = Promise.all(this.images.map(this.getPromise));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageLoader.prototype.findImages = function(images, container) {
|
||||||
|
var backgrounds = container.parseBackgroundImages();
|
||||||
|
var backgroundImages = backgrounds.filter(this.isImageBackground).map(this.getBackgroundUrl).filter(this.imageExists(images)).map(this.loadImage, this);
|
||||||
|
return images.concat(backgroundImages);
|
||||||
|
};
|
||||||
|
|
||||||
|
ImageLoader.prototype.getBackgroundUrl = function(imageData) {
|
||||||
|
return imageData.args[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
ImageLoader.prototype.isImageBackground = function(imageData) {
|
||||||
|
return imageData.method === "url";
|
||||||
|
};
|
||||||
|
|
||||||
|
ImageLoader.prototype.loadImage = function(src) {
|
||||||
|
if (src.match(/data:image\/.*;base64,/i)) {
|
||||||
|
return new ImageContainer(src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, ''), false);
|
||||||
|
} else if (this.isSameOrigin(src) || this.options.allowTaint === true) {
|
||||||
|
return new ImageContainer(src, false);
|
||||||
|
} else if (this.support.cors && !this.options.allowTaint && this.options.useCORS) {
|
||||||
|
return new ImageContainer(src, true);
|
||||||
|
} else if (this.options.proxy) {
|
||||||
|
return new ProxyImageContainer(src);
|
||||||
|
} else {
|
||||||
|
return new DummyImageContainer(src);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ImageLoader.prototype.imageExists = function(images) {
|
||||||
|
return function(newImage) {
|
||||||
|
return !images.some(function(image) {
|
||||||
|
return image.src !== newImage.src;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
ImageLoader.prototype.isSameOrigin = function(url) {
|
||||||
|
var link = this.link || (this.link = document.createElement("a"));
|
||||||
|
link.href = url;
|
||||||
|
link.href = link.href; // IE9, LOL! - http://jsfiddle.net/niklasvh/2e48b/
|
||||||
|
var origin = link.protocol + link.host;
|
||||||
|
return (origin === this.origin);
|
||||||
|
};
|
||||||
|
|
||||||
|
ImageLoader.prototype.getPromise = function(container) {
|
||||||
|
return container.promise;
|
||||||
|
};
|
@ -47,3 +47,101 @@ NodeContainer.prototype.fontWeight = function() {
|
|||||||
}
|
}
|
||||||
return weight;
|
return weight;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
NodeContainer.prototype.parseBackgroundImages = function() {
|
||||||
|
var whitespace = ' \r\n\t',
|
||||||
|
method, definition, prefix, prefix_i, block, results = [],
|
||||||
|
mode = 0, numParen = 0, quote, args;
|
||||||
|
var appendResult = function() {
|
||||||
|
if(method) {
|
||||||
|
if (definition.substr(0, 1) === '"') {
|
||||||
|
definition = definition.substr(1, definition.length - 2);
|
||||||
|
}
|
||||||
|
if (definition) {
|
||||||
|
args.push(definition);
|
||||||
|
}
|
||||||
|
if (method.substr(0, 1) === '-' && (prefix_i = method.indexOf('-', 1 ) + 1) > 0) {
|
||||||
|
prefix = method.substr(0, prefix_i);
|
||||||
|
method = method.substr(prefix_i);
|
||||||
|
}
|
||||||
|
results.push({
|
||||||
|
prefix: prefix,
|
||||||
|
method: method.toLowerCase(),
|
||||||
|
value: block,
|
||||||
|
args: args,
|
||||||
|
image: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
args = [];
|
||||||
|
method = prefix = definition = block = '';
|
||||||
|
};
|
||||||
|
args = [];
|
||||||
|
method = prefix = definition = block = '';
|
||||||
|
this.css("backgroundImage").split("").forEach(function(c) {
|
||||||
|
if (mode === 0 && whitespace.indexOf(c) > -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch(c) {
|
||||||
|
case '"':
|
||||||
|
if(!quote) {
|
||||||
|
quote = c;
|
||||||
|
}
|
||||||
|
else if(quote === c) {
|
||||||
|
quote = null;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '(':
|
||||||
|
if(quote) {
|
||||||
|
break;
|
||||||
|
} else if(mode === 0) {
|
||||||
|
mode = 1;
|
||||||
|
block += c;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
numParen++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ')':
|
||||||
|
if (quote) {
|
||||||
|
break;
|
||||||
|
} else if(mode === 1) {
|
||||||
|
if(numParen === 0) {
|
||||||
|
mode = 0;
|
||||||
|
block += c;
|
||||||
|
appendResult();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
numParen--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ',':
|
||||||
|
if (quote) {
|
||||||
|
break;
|
||||||
|
} else if(mode === 0) {
|
||||||
|
appendResult();
|
||||||
|
return;
|
||||||
|
} else if (mode === 1) {
|
||||||
|
if (numParen === 0 && !method.match(/^url$/i)) {
|
||||||
|
args.push(definition);
|
||||||
|
definition = '';
|
||||||
|
block += c;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
block += c;
|
||||||
|
if (mode === 0) {
|
||||||
|
method += c;
|
||||||
|
} else {
|
||||||
|
definition += c;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
appendResult();
|
||||||
|
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
function Support() {
|
function Support() {
|
||||||
this.rangeBounds = this.testRangeBounds();
|
this.rangeBounds = this.testRangeBounds();
|
||||||
|
this.cors = this.testCORS();
|
||||||
}
|
}
|
||||||
|
|
||||||
Support.prototype.testRangeBounds = function() {
|
Support.prototype.testRangeBounds = function() {
|
||||||
@ -26,3 +27,7 @@ Support.prototype.testRangeBounds = function() {
|
|||||||
|
|
||||||
return support;
|
return support;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Support.prototype.testCORS = function() {
|
||||||
|
return typeof((new Image()).crossOrigin) !== "undefined";
|
||||||
|
};
|
||||||
|
@ -11,9 +11,9 @@ var h2cSelector, h2cOptions;
|
|||||||
|
|
||||||
document.write(srcStart + '/tests/assets/jquery-1.6.2.js' + scrEnd);
|
document.write(srcStart + '/tests/assets/jquery-1.6.2.js' + scrEnd);
|
||||||
document.write(srcStart + '/tests/assets/jquery.plugin.html2canvas.js' + scrEnd);
|
document.write(srcStart + '/tests/assets/jquery.plugin.html2canvas.js' + scrEnd);
|
||||||
var html2canvas = ['nodecontainer', 'stackingcontext', 'textcontainer', 'support', 'core', 'renderer', 'renderers/canvas'], i;
|
var html2canvas = ['nodecontainer', 'stackingcontext', 'textcontainer', 'support', 'imagecontainer', 'imageloader', 'core', 'renderer', 'renderers/canvas'], i;
|
||||||
for (i = 0; i < html2canvas.length; ++i) {
|
for (i = 0; i < html2canvas.length; ++i) {
|
||||||
document.write(srcStart + '/new/' + html2canvas[i] + '.js?' + Math.random() + scrEnd);
|
document.write(srcStart + '/src/' + html2canvas[i] + '.js?' + Math.random() + scrEnd);
|
||||||
}
|
}
|
||||||
window.onload = function() {
|
window.onload = function() {
|
||||||
h2cSelector = [document.body];
|
h2cSelector = [document.body];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user