mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
Draw <img> elements
This commit is contained in:
parent
2afdcaff35
commit
74cb3466ec
@ -50,10 +50,10 @@ module.exports = function(grunt) {
|
|||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
files: 'src/**/*',
|
files: 'src/**/*',
|
||||||
tasks: ['build', 'jshint']
|
tasks: ['jshint', 'build']
|
||||||
},
|
},
|
||||||
jshint: {
|
jshint: {
|
||||||
all: ['<%= concat.dist.dest %>'],
|
all: ['src/**/*.js', '!src/promise.js'],
|
||||||
options: grunt.file.readJSON('./.jshintrc')
|
options: grunt.file.readJSON('./.jshintrc')
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -80,7 +80,7 @@ module.exports = function(grunt) {
|
|||||||
// Default task.
|
// Default task.
|
||||||
grunt.registerTask('server', ['connect']);
|
grunt.registerTask('server', ['connect']);
|
||||||
grunt.registerTask('build', ['concat', 'uglify']);
|
grunt.registerTask('build', ['concat', 'uglify']);
|
||||||
grunt.registerTask('default', ['concat', 'jshint', 'qunit', 'uglify']);
|
grunt.registerTask('default', ['jshint', 'concat', 'qunit', 'uglify']);
|
||||||
grunt.registerTask('travis', ['concat', 'jshint', 'qunit', 'uglify', 'webdriver']);
|
grunt.registerTask('travis', ['jshint', 'concat','qunit', 'uglify', 'webdriver']);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -77,6 +77,7 @@ function createWindowClone(ownerDocument, width, height) {
|
|||||||
documentClone.close();
|
documentClone.close();
|
||||||
|
|
||||||
documentClone.replaceChild(documentClone.adoptNode(documentElement), documentClone.documentElement);
|
documentClone.replaceChild(documentClone.adoptNode(documentElement), documentClone.documentElement);
|
||||||
|
container.contentWindow.scrollTo(window.scrollX, window.scrollY);
|
||||||
var div = documentClone.createElement("div");
|
var div = documentClone.createElement("div");
|
||||||
div.className = "html2canvas-ready-test";
|
div.className = "html2canvas-ready-test";
|
||||||
documentClone.body.appendChild(div);
|
documentClone.body.appendChild(div);
|
||||||
@ -259,10 +260,14 @@ NodeParser.prototype.parse = function(stack) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
NodeParser.prototype.paint = function(container) {
|
NodeParser.prototype.paint = function(container) {
|
||||||
if (isTextNode(container)) {
|
try {
|
||||||
this.paintText(container);
|
if (isTextNode(container)) {
|
||||||
} else {
|
this.paintText(container);
|
||||||
this.paintNode(container);
|
} else {
|
||||||
|
this.paintNode(container);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
log(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -277,6 +282,17 @@ NodeParser.prototype.paintNode = function(container) {
|
|||||||
this.renderer.renderBackground(container, bounds);
|
this.renderer.renderBackground(container, bounds);
|
||||||
}, this);
|
}, this);
|
||||||
this.renderer.renderBorders(borderData.borders);
|
this.renderer.renderBorders(borderData.borders);
|
||||||
|
|
||||||
|
switch(container.node.nodeName) {
|
||||||
|
case "IMG":
|
||||||
|
var imageContainer = this.images.get(container.node.src);
|
||||||
|
if (imageContainer) {
|
||||||
|
this.renderer.renderImage(container, bounds, borderData, imageContainer.image);
|
||||||
|
} else {
|
||||||
|
log("Error loading <img>", container.node.src);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
NodeParser.prototype.paintText = function(container) {
|
NodeParser.prototype.paintText = function(container) {
|
||||||
@ -613,10 +629,23 @@ function ImageLoader(options, support) {
|
|||||||
this.origin = window.location.protocol + window.location.host;
|
this.origin = window.location.protocol + window.location.host;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageLoader.prototype.findImages = function(images, container) {
|
ImageLoader.prototype.findImages = function(nodes) {
|
||||||
var backgrounds = container.parseBackgroundImages();
|
var images = [];
|
||||||
var backgroundImages = backgrounds.filter(this.isImageBackground).map(this.getBackgroundUrl).filter(this.imageExists(images)).map(this.loadImage, this);
|
nodes.filter(isImage).map(src).forEach(this.addImage(images, this.loadImage), this);
|
||||||
return images.concat(backgroundImages);
|
return images;
|
||||||
|
};
|
||||||
|
|
||||||
|
ImageLoader.prototype.findBackgroundImage = function(images, container) {
|
||||||
|
container.parseBackgroundImages().filter(this.isImageBackground).map(this.getBackgroundUrl).forEach(this.addImage(images, this.loadImage), this);
|
||||||
|
return images;
|
||||||
|
};
|
||||||
|
|
||||||
|
ImageLoader.prototype.addImage = function(images, callback) {
|
||||||
|
return function(newImage) {
|
||||||
|
if (!this.imageExists(images, newImage)) {
|
||||||
|
images.splice(0, 0, callback.apply(this, arguments));
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
ImageLoader.prototype.getBackgroundUrl = function(imageData) {
|
ImageLoader.prototype.getBackgroundUrl = function(imageData) {
|
||||||
@ -641,12 +670,10 @@ ImageLoader.prototype.loadImage = function(src) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ImageLoader.prototype.imageExists = function(images) {
|
ImageLoader.prototype.imageExists = function(images, src) {
|
||||||
return function(newImage) {
|
return images.some(function(image) {
|
||||||
return !images.some(function(image) {
|
return image.src === src;
|
||||||
return image.src !== newImage.src;
|
});
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ImageLoader.prototype.isSameOrigin = function(url) {
|
ImageLoader.prototype.isSameOrigin = function(url) {
|
||||||
@ -669,11 +696,19 @@ ImageLoader.prototype.get = function(src) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ImageLoader.prototype.fetch = function(nodes) {
|
ImageLoader.prototype.fetch = function(nodes) {
|
||||||
this.images = nodes.reduce(bind(this.findImages, this), []);
|
this.images = nodes.reduce(bind(this.findBackgroundImage, this), this.findImages(nodes));
|
||||||
this.ready = Promise.all(this.images.map(this.getPromise));
|
this.ready = Promise.all(this.images.map(this.getPromise));
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function isImage(container) {
|
||||||
|
return container.node.nodeName === "IMG";
|
||||||
|
}
|
||||||
|
|
||||||
|
function src(container) {
|
||||||
|
return container.node.src;
|
||||||
|
}
|
||||||
|
|
||||||
function log() {
|
function log() {
|
||||||
if (window.html2canvas.logging && window.console && window.console.log) {
|
if (window.html2canvas.logging && window.console && window.console.log) {
|
||||||
window.console.log.apply(window.console, [(Date.now() - window.html2canvas.start) + "ms", "html2canvas:"].concat([].slice.call(arguments, 0)));
|
window.console.log.apply(window.console, [(Date.now() - window.html2canvas.start) + "ms", "html2canvas:"].concat([].slice.call(arguments, 0)));
|
||||||
@ -931,6 +966,26 @@ function Renderer(width, height, images) {
|
|||||||
this.images = images;
|
this.images = images;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Renderer.prototype.renderImage = function(container, bounds, borderData, image) {
|
||||||
|
var paddingLeft = container.cssInt('paddingLeft'),
|
||||||
|
paddingTop = container.cssInt('paddingTop'),
|
||||||
|
paddingRight = container.cssInt('paddingRight'),
|
||||||
|
paddingBottom = container.cssInt('paddingBottom'),
|
||||||
|
borders = borderData.borders;
|
||||||
|
|
||||||
|
this.drawImage(
|
||||||
|
image,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
image.width,
|
||||||
|
image.height,
|
||||||
|
bounds.left + paddingLeft + borders[3].width,
|
||||||
|
bounds.top + paddingTop + borders[0].width,
|
||||||
|
bounds.width - (borders[1].width + borders[3].width + paddingLeft + paddingRight),
|
||||||
|
bounds.height - (borders[0].width + borders[2].width + paddingTop + paddingBottom)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
Renderer.prototype.renderBackground = function(container, bounds) {
|
Renderer.prototype.renderBackground = function(container, bounds) {
|
||||||
if (bounds.height > 0 && bounds.width > 0) {
|
if (bounds.height > 0 && bounds.width > 0) {
|
||||||
this.renderBackgroundColor(container, bounds);
|
this.renderBackgroundColor(container, bounds);
|
||||||
@ -1021,6 +1076,10 @@ CanvasRenderer.prototype.drawShape = function(shape, color) {
|
|||||||
this.setFillStyle(color).fill();
|
this.setFillStyle(color).fill();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CanvasRenderer.prototype.drawImage = function(image, sx, sy, sw, sh, dx, dy, dw, dh) {
|
||||||
|
this.ctx.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);
|
||||||
|
};
|
||||||
|
|
||||||
CanvasRenderer.prototype.clip = function(shape, callback, context) {
|
CanvasRenderer.prototype.clip = function(shape, callback, context) {
|
||||||
this.ctx.save();
|
this.ctx.save();
|
||||||
this.shape(shape).clip();
|
this.shape(shape).clip();
|
||||||
@ -1057,7 +1116,7 @@ CanvasRenderer.prototype.backgroundRepeatShape = function(imageContainer, backgr
|
|||||||
["line", Math.round(left), Math.round(height + top)]
|
["line", Math.round(left), Math.round(height + top)]
|
||||||
];
|
];
|
||||||
this.clip(shape, function() {
|
this.clip(shape, function() {
|
||||||
this.renderBackgroundRepeat(imageContainer, backgroundPosition, bounds);
|
this.renderBackgroundRepeat(imageContainer, backgroundPosition, size, bounds);
|
||||||
}, this);
|
}, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
2
build/html2canvas.min.js
vendored
2
build/html2canvas.min.js
vendored
File diff suppressed because one or more lines are too long
24
src/core.js
24
src/core.js
@ -68,6 +68,7 @@ function createWindowClone(ownerDocument, width, height) {
|
|||||||
documentClone.close();
|
documentClone.close();
|
||||||
|
|
||||||
documentClone.replaceChild(documentClone.adoptNode(documentElement), documentClone.documentElement);
|
documentClone.replaceChild(documentClone.adoptNode(documentElement), documentClone.documentElement);
|
||||||
|
container.contentWindow.scrollTo(window.scrollX, window.scrollY);
|
||||||
var div = documentClone.createElement("div");
|
var div = documentClone.createElement("div");
|
||||||
div.className = "html2canvas-ready-test";
|
div.className = "html2canvas-ready-test";
|
||||||
documentClone.body.appendChild(div);
|
documentClone.body.appendChild(div);
|
||||||
@ -250,10 +251,14 @@ NodeParser.prototype.parse = function(stack) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
NodeParser.prototype.paint = function(container) {
|
NodeParser.prototype.paint = function(container) {
|
||||||
if (isTextNode(container)) {
|
try {
|
||||||
this.paintText(container);
|
if (isTextNode(container)) {
|
||||||
} else {
|
this.paintText(container);
|
||||||
this.paintNode(container);
|
} else {
|
||||||
|
this.paintNode(container);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
log(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -268,6 +273,17 @@ NodeParser.prototype.paintNode = function(container) {
|
|||||||
this.renderer.renderBackground(container, bounds);
|
this.renderer.renderBackground(container, bounds);
|
||||||
}, this);
|
}, this);
|
||||||
this.renderer.renderBorders(borderData.borders);
|
this.renderer.renderBorders(borderData.borders);
|
||||||
|
|
||||||
|
switch(container.node.nodeName) {
|
||||||
|
case "IMG":
|
||||||
|
var imageContainer = this.images.get(container.node.src);
|
||||||
|
if (imageContainer) {
|
||||||
|
this.renderer.renderImage(container, bounds, borderData, imageContainer.image);
|
||||||
|
} else {
|
||||||
|
log("Error loading <img>", container.node.src);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
NodeParser.prototype.paintText = function(container) {
|
NodeParser.prototype.paintText = function(container) {
|
||||||
|
@ -5,10 +5,23 @@ function ImageLoader(options, support) {
|
|||||||
this.origin = window.location.protocol + window.location.host;
|
this.origin = window.location.protocol + window.location.host;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageLoader.prototype.findImages = function(images, container) {
|
ImageLoader.prototype.findImages = function(nodes) {
|
||||||
var backgrounds = container.parseBackgroundImages();
|
var images = [];
|
||||||
var backgroundImages = backgrounds.filter(this.isImageBackground).map(this.getBackgroundUrl).filter(this.imageExists(images)).map(this.loadImage, this);
|
nodes.filter(isImage).map(src).forEach(this.addImage(images, this.loadImage), this);
|
||||||
return images.concat(backgroundImages);
|
return images;
|
||||||
|
};
|
||||||
|
|
||||||
|
ImageLoader.prototype.findBackgroundImage = function(images, container) {
|
||||||
|
container.parseBackgroundImages().filter(this.isImageBackground).map(this.getBackgroundUrl).forEach(this.addImage(images, this.loadImage), this);
|
||||||
|
return images;
|
||||||
|
};
|
||||||
|
|
||||||
|
ImageLoader.prototype.addImage = function(images, callback) {
|
||||||
|
return function(newImage) {
|
||||||
|
if (!this.imageExists(images, newImage)) {
|
||||||
|
images.splice(0, 0, callback.apply(this, arguments));
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
ImageLoader.prototype.getBackgroundUrl = function(imageData) {
|
ImageLoader.prototype.getBackgroundUrl = function(imageData) {
|
||||||
@ -33,12 +46,10 @@ ImageLoader.prototype.loadImage = function(src) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ImageLoader.prototype.imageExists = function(images) {
|
ImageLoader.prototype.imageExists = function(images, src) {
|
||||||
return function(newImage) {
|
return images.some(function(image) {
|
||||||
return !images.some(function(image) {
|
return image.src === src;
|
||||||
return image.src !== newImage.src;
|
});
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ImageLoader.prototype.isSameOrigin = function(url) {
|
ImageLoader.prototype.isSameOrigin = function(url) {
|
||||||
@ -61,7 +72,15 @@ ImageLoader.prototype.get = function(src) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ImageLoader.prototype.fetch = function(nodes) {
|
ImageLoader.prototype.fetch = function(nodes) {
|
||||||
this.images = nodes.reduce(bind(this.findImages, this), []);
|
this.images = nodes.reduce(bind(this.findBackgroundImage, this), this.findImages(nodes));
|
||||||
this.ready = Promise.all(this.images.map(this.getPromise));
|
this.ready = Promise.all(this.images.map(this.getPromise));
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function isImage(container) {
|
||||||
|
return container.node.nodeName === "IMG";
|
||||||
|
}
|
||||||
|
|
||||||
|
function src(container) {
|
||||||
|
return container.node.src;
|
||||||
|
}
|
||||||
|
@ -4,6 +4,26 @@ function Renderer(width, height, images) {
|
|||||||
this.images = images;
|
this.images = images;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Renderer.prototype.renderImage = function(container, bounds, borderData, image) {
|
||||||
|
var paddingLeft = container.cssInt('paddingLeft'),
|
||||||
|
paddingTop = container.cssInt('paddingTop'),
|
||||||
|
paddingRight = container.cssInt('paddingRight'),
|
||||||
|
paddingBottom = container.cssInt('paddingBottom'),
|
||||||
|
borders = borderData.borders;
|
||||||
|
|
||||||
|
this.drawImage(
|
||||||
|
image,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
image.width,
|
||||||
|
image.height,
|
||||||
|
bounds.left + paddingLeft + borders[3].width,
|
||||||
|
bounds.top + paddingTop + borders[0].width,
|
||||||
|
bounds.width - (borders[1].width + borders[3].width + paddingLeft + paddingRight),
|
||||||
|
bounds.height - (borders[0].width + borders[2].width + paddingTop + paddingBottom)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
Renderer.prototype.renderBackground = function(container, bounds) {
|
Renderer.prototype.renderBackground = function(container, bounds) {
|
||||||
if (bounds.height > 0 && bounds.width > 0) {
|
if (bounds.height > 0 && bounds.width > 0) {
|
||||||
this.renderBackgroundColor(container, bounds);
|
this.renderBackgroundColor(container, bounds);
|
||||||
|
@ -23,6 +23,10 @@ CanvasRenderer.prototype.drawShape = function(shape, color) {
|
|||||||
this.setFillStyle(color).fill();
|
this.setFillStyle(color).fill();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CanvasRenderer.prototype.drawImage = function(image, sx, sy, sw, sh, dx, dy, dw, dh) {
|
||||||
|
this.ctx.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);
|
||||||
|
};
|
||||||
|
|
||||||
CanvasRenderer.prototype.clip = function(shape, callback, context) {
|
CanvasRenderer.prototype.clip = function(shape, callback, context) {
|
||||||
this.ctx.save();
|
this.ctx.save();
|
||||||
this.shape(shape).clip();
|
this.shape(shape).clip();
|
||||||
@ -59,7 +63,7 @@ CanvasRenderer.prototype.backgroundRepeatShape = function(imageContainer, backgr
|
|||||||
["line", Math.round(left), Math.round(height + top)]
|
["line", Math.round(left), Math.round(height + top)]
|
||||||
];
|
];
|
||||||
this.clip(shape, function() {
|
this.clip(shape, function() {
|
||||||
this.renderBackgroundRepeat(imageContainer, backgroundPosition, bounds);
|
this.renderBackgroundRepeat(imageContainer, backgroundPosition, size, bounds);
|
||||||
}, this);
|
}, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user