mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
Add svg rendering with fabric.js
This commit is contained in:
parent
2e2d722e3d
commit
ba9d5201cf
@ -14,6 +14,6 @@
|
||||
"globals": {
|
||||
"jQuery": true
|
||||
},
|
||||
"predef": ["NodeParser", "NodeContainer", "StackingContext", "TextContainer", "ImageLoader", "CanvasRenderer", "Renderer", "Support", "bind", "Promise", "getBounds", "offsetBounds",
|
||||
"ImageContainer", "ProxyImageContainer", "DummyImageContainer", "Font", "FontMetrics", "GradientContainer", "LinearGradientContainer", "WebkitGradientContainer", "log", "smallImage", "parseBackgrounds"]
|
||||
"predef": ["NodeParser", "NodeContainer", "StackingContext", "TextContainer", "ImageLoader", "CanvasRenderer", "Renderer", "Support", "bind", "Promise", "getBounds", "offsetBounds", "XHR",
|
||||
"ImageContainer", "ProxyImageContainer", "DummyImageContainer", "Font", "FontMetrics", "GradientContainer", "LinearGradientContainer", "WebkitGradientContainer", "SVGContainer", "html2canvas", "log", "smallImage", "parseBackgrounds"]
|
||||
}
|
||||
|
28
Gruntfile.js
28
Gruntfile.js
@ -9,7 +9,7 @@ module.exports = function(grunt) {
|
||||
' Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>' +
|
||||
'\n\n Released under <%= _.pluck(pkg.licenses, "type").join(", ") %> License\n*/\n',
|
||||
pre: '\n(function(window, document, undefined){\n\n',
|
||||
post: '\n})(window,document);'
|
||||
post: '\n})(window, document);'
|
||||
};
|
||||
|
||||
// Project configuration.
|
||||
@ -23,13 +23,23 @@ module.exports = function(grunt) {
|
||||
concat: {
|
||||
dist: {
|
||||
src: [
|
||||
'src/promise.js', 'src/fallback.js', 'src/**/*.js'
|
||||
'src/promise.js', 'src/fallback.js', 'src/*.js', 'src/renderers/*.js'
|
||||
],
|
||||
dest: 'dist/<%= pkg.name %>.js'
|
||||
dest: 'dist/<%= pkg.name %>.js',
|
||||
options:{
|
||||
banner: meta.banner + meta.pre,
|
||||
footer: meta.post
|
||||
}
|
||||
},
|
||||
options:{
|
||||
banner: meta.banner + meta.pre,
|
||||
footer: meta.post
|
||||
svg: {
|
||||
src: [
|
||||
'src/fabric/dist/fabric.js'
|
||||
],
|
||||
dest: 'dist/<%= pkg.name %>.svg.js',
|
||||
options:{
|
||||
banner: meta.banner + '\n(function(window, document, exports, undefined){\n\n',
|
||||
footer: '\n})(window, document, html2canvas);'
|
||||
}
|
||||
}
|
||||
},
|
||||
connect: {
|
||||
@ -73,6 +83,10 @@ module.exports = function(grunt) {
|
||||
src: ['<%= concat.dist.dest %>'],
|
||||
dest: 'dist/<%= pkg.name %>.min.js'
|
||||
},
|
||||
svg: {
|
||||
src: ['<%= concat.svg.dest %>'],
|
||||
dest: 'dist/<%= pkg.name %>.svg.min.js'
|
||||
},
|
||||
options: {
|
||||
banner: meta.banner
|
||||
}
|
||||
@ -82,7 +96,7 @@ module.exports = function(grunt) {
|
||||
tasks: ['jshint', 'build']
|
||||
},
|
||||
jshint: {
|
||||
all: ['src/**/*.js', '!src/promise.js'],
|
||||
all: ['src/*.js', 'src/renderers/*.js', '!src/promise.js'],
|
||||
options: grunt.file.readJSON('./.jshintrc')
|
||||
},
|
||||
webdriver: {
|
||||
|
217
dist/html2canvas.js
vendored
217
dist/html2canvas.js
vendored
@ -323,6 +323,8 @@ ImageLoader.prototype.loadImage = function(imageData) {
|
||||
var src = imageData.args[0];
|
||||
if (src.match(/data:image\/.*;base64,/i)) {
|
||||
return new ImageContainer(src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, ''), false);
|
||||
} else if (/(.+).svg$/i.test(src)) {
|
||||
return new SVGContainer(src);
|
||||
} 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) {
|
||||
@ -1676,6 +1678,133 @@ Renderer.prototype.isTransparent = function(color) {
|
||||
return (!color || color === "transparent" || color === "rgba(0, 0, 0, 0)");
|
||||
};
|
||||
|
||||
function StackingContext(hasOwnStacking, opacity, element, parent) {
|
||||
NodeContainer.call(this, element, parent);
|
||||
this.ownStacking = hasOwnStacking;
|
||||
this.contexts = [];
|
||||
this.children = [];
|
||||
this.opacity = (this.parent ? this.parent.stack.opacity : 1) * opacity;
|
||||
}
|
||||
|
||||
StackingContext.prototype = Object.create(NodeContainer.prototype);
|
||||
|
||||
StackingContext.prototype.getParentStack = function(context) {
|
||||
var parentStack = (this.parent) ? this.parent.stack : null;
|
||||
return parentStack ? (parentStack.ownStacking ? parentStack : parentStack.getParentStack(context)) : context.stack;
|
||||
};
|
||||
|
||||
function Support(document) {
|
||||
this.rangeBounds = this.testRangeBounds(document);
|
||||
this.cors = this.testCORS();
|
||||
}
|
||||
|
||||
Support.prototype.testRangeBounds = function(document) {
|
||||
var range, testElement, rangeBounds, rangeHeight, support = false;
|
||||
|
||||
if (document.createRange) {
|
||||
range = document.createRange();
|
||||
if (range.getBoundingClientRect) {
|
||||
testElement = document.createElement('boundtest');
|
||||
testElement.style.height = "123px";
|
||||
testElement.style.display = "block";
|
||||
document.body.appendChild(testElement);
|
||||
|
||||
range.selectNode(testElement);
|
||||
rangeBounds = range.getBoundingClientRect();
|
||||
rangeHeight = rangeBounds.height;
|
||||
|
||||
if (rangeHeight === 123) {
|
||||
support = true;
|
||||
}
|
||||
document.body.removeChild(testElement);
|
||||
}
|
||||
}
|
||||
|
||||
return support;
|
||||
};
|
||||
|
||||
Support.prototype.testCORS = function() {
|
||||
return typeof((new Image()).crossOrigin) !== "undefined";
|
||||
};
|
||||
|
||||
function SVGContainer(src) {
|
||||
this.src = src;
|
||||
this.image = null;
|
||||
var self = this;
|
||||
this.promise = XHR(src).then(function(svg) {
|
||||
return new Promise(function(resolve) {
|
||||
html2canvas.fabric.loadSVGFromString(svg, function (objects, options) {
|
||||
var canvas = new html2canvas.fabric.StaticCanvas('c');
|
||||
self.image = canvas.lowerCanvasEl;
|
||||
canvas
|
||||
.setWidth(options.width)
|
||||
.setHeight(options.height)
|
||||
.add(html2canvas.fabric.util.groupSVGElements(objects, options))
|
||||
.renderAll();
|
||||
resolve(canvas.lowerCanvasEl);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function TextContainer(node, parent) {
|
||||
NodeContainer.call(this, node, parent);
|
||||
}
|
||||
|
||||
TextContainer.prototype = Object.create(NodeContainer.prototype);
|
||||
|
||||
TextContainer.prototype.applyTextTransform = function() {
|
||||
this.node.data = this.transform(this.parent.css("textTransform"));
|
||||
};
|
||||
|
||||
TextContainer.prototype.transform = function(transform) {
|
||||
var text = this.node.data;
|
||||
switch(transform){
|
||||
case "lowercase":
|
||||
return text.toLowerCase();
|
||||
case "capitalize":
|
||||
return text.replace(/(^|\s|:|-|\(|\))([a-z])/g, capitalize);
|
||||
case "uppercase":
|
||||
return text.toUpperCase();
|
||||
default:
|
||||
return text;
|
||||
}
|
||||
};
|
||||
|
||||
function capitalize(m, p1, p2) {
|
||||
if (m.length > 0) {
|
||||
return p1 + p2.toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
function WebkitGradientContainer(imageData) {
|
||||
GradientContainer.apply(this, arguments);
|
||||
this.type = (imageData.args[0] === "linear") ? this.TYPES.LINEAR : this.TYPES.RADIAL;
|
||||
}
|
||||
|
||||
WebkitGradientContainer.prototype = Object.create(GradientContainer.prototype);
|
||||
|
||||
function XHR(url) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url);
|
||||
|
||||
xhr.onload = function() {
|
||||
if (xhr.status === 200) {
|
||||
resolve(xhr.response);
|
||||
} else {
|
||||
reject(Error(xhr.statusText));
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = function() {
|
||||
reject(Error("Network Error"));
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
|
||||
function CanvasRenderer(width, height) {
|
||||
Renderer.apply(this, arguments);
|
||||
this.canvas = document.createElement("canvas");
|
||||
@ -1826,90 +1955,4 @@ CanvasRenderer.prototype.resizeImage = function(imageContainer, size) {
|
||||
return canvas;
|
||||
};
|
||||
|
||||
function StackingContext(hasOwnStacking, opacity, element, parent) {
|
||||
NodeContainer.call(this, element, parent);
|
||||
this.ownStacking = hasOwnStacking;
|
||||
this.contexts = [];
|
||||
this.children = [];
|
||||
this.opacity = (this.parent ? this.parent.stack.opacity : 1) * opacity;
|
||||
}
|
||||
|
||||
StackingContext.prototype = Object.create(NodeContainer.prototype);
|
||||
|
||||
StackingContext.prototype.getParentStack = function(context) {
|
||||
var parentStack = (this.parent) ? this.parent.stack : null;
|
||||
return parentStack ? (parentStack.ownStacking ? parentStack : parentStack.getParentStack(context)) : context.stack;
|
||||
};
|
||||
|
||||
function Support(document) {
|
||||
this.rangeBounds = this.testRangeBounds(document);
|
||||
this.cors = this.testCORS();
|
||||
}
|
||||
|
||||
Support.prototype.testRangeBounds = function(document) {
|
||||
var range, testElement, rangeBounds, rangeHeight, support = false;
|
||||
|
||||
if (document.createRange) {
|
||||
range = document.createRange();
|
||||
if (range.getBoundingClientRect) {
|
||||
testElement = document.createElement('boundtest');
|
||||
testElement.style.height = "123px";
|
||||
testElement.style.display = "block";
|
||||
document.body.appendChild(testElement);
|
||||
|
||||
range.selectNode(testElement);
|
||||
rangeBounds = range.getBoundingClientRect();
|
||||
rangeHeight = rangeBounds.height;
|
||||
|
||||
if (rangeHeight === 123) {
|
||||
support = true;
|
||||
}
|
||||
document.body.removeChild(testElement);
|
||||
}
|
||||
}
|
||||
|
||||
return support;
|
||||
};
|
||||
|
||||
Support.prototype.testCORS = function() {
|
||||
return typeof((new Image()).crossOrigin) !== "undefined";
|
||||
};
|
||||
|
||||
function TextContainer(node, parent) {
|
||||
NodeContainer.call(this, node, parent);
|
||||
}
|
||||
|
||||
TextContainer.prototype = Object.create(NodeContainer.prototype);
|
||||
|
||||
TextContainer.prototype.applyTextTransform = function() {
|
||||
this.node.data = this.transform(this.parent.css("textTransform"));
|
||||
};
|
||||
|
||||
TextContainer.prototype.transform = function(transform) {
|
||||
var text = this.node.data;
|
||||
switch(transform){
|
||||
case "lowercase":
|
||||
return text.toLowerCase();
|
||||
case "capitalize":
|
||||
return text.replace(/(^|\s|:|-|\(|\))([a-z])/g, capitalize);
|
||||
case "uppercase":
|
||||
return text.toUpperCase();
|
||||
default:
|
||||
return text;
|
||||
}
|
||||
};
|
||||
|
||||
function capitalize(m, p1, p2) {
|
||||
if (m.length > 0) {
|
||||
return p1 + p2.toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
function WebkitGradientContainer(imageData) {
|
||||
GradientContainer.apply(this, arguments);
|
||||
this.type = (imageData.args[0] === "linear") ? this.TYPES.LINEAR : this.TYPES.RADIAL;
|
||||
}
|
||||
|
||||
WebkitGradientContainer.prototype = Object.create(GradientContainer.prototype);
|
||||
|
||||
})(window,document);
|
||||
})(window, document);
|
4
dist/html2canvas.min.js
vendored
4
dist/html2canvas.min.js
vendored
File diff suppressed because one or more lines are too long
22713
dist/html2canvas.svg.js
vendored
Normal file
22713
dist/html2canvas.svg.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
13
dist/html2canvas.svg.min.js
vendored
Normal file
13
dist/html2canvas.svg.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -34,6 +34,8 @@ ImageLoader.prototype.loadImage = function(imageData) {
|
||||
var src = imageData.args[0];
|
||||
if (src.match(/data:image\/.*;base64,/i)) {
|
||||
return new ImageContainer(src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, ''), false);
|
||||
} else if (/(.+).svg$/i.test(src)) {
|
||||
return new SVGContainer(src);
|
||||
} 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) {
|
||||
|
19
src/svgcontainer.js
Normal file
19
src/svgcontainer.js
Normal file
@ -0,0 +1,19 @@
|
||||
function SVGContainer(src) {
|
||||
this.src = src;
|
||||
this.image = null;
|
||||
var self = this;
|
||||
this.promise = XHR(src).then(function(svg) {
|
||||
return new Promise(function(resolve) {
|
||||
html2canvas.fabric.loadSVGFromString(svg, function (objects, options) {
|
||||
var canvas = new html2canvas.fabric.StaticCanvas('c');
|
||||
self.image = canvas.lowerCanvasEl;
|
||||
canvas
|
||||
.setWidth(options.width)
|
||||
.setHeight(options.height)
|
||||
.add(html2canvas.fabric.util.groupSVGElements(objects, options))
|
||||
.renderAll();
|
||||
resolve(canvas.lowerCanvasEl);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
20
src/xhr.js
Normal file
20
src/xhr.js
Normal file
@ -0,0 +1,20 @@
|
||||
function XHR(url) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url);
|
||||
|
||||
xhr.onload = function() {
|
||||
if (xhr.status === 200) {
|
||||
resolve(xhr.response);
|
||||
} else {
|
||||
reject(Error(xhr.statusText));
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = function() {
|
||||
reject(Error("Network Error"));
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
});
|
||||
}
|
@ -12,10 +12,12 @@ var h2cSelector, h2cOptions;
|
||||
}
|
||||
|
||||
var sources = ['log', 'nodecontainer', 'stackingcontext', 'textcontainer', 'support', 'imagecontainer', 'dummyimagecontainer', 'proxyimagecontainer', 'gradientcontainer',
|
||||
'lineargradientcontainer', 'webkitgradientcontainer', 'imageloader', 'nodeparser', 'font', 'fontmetrics', 'core', 'renderer', 'promise', 'renderers/canvas'];
|
||||
'lineargradientcontainer', 'webkitgradientcontainer', 'svgcontainer', 'imageloader', 'nodeparser', 'font', 'fontmetrics', 'core', 'renderer', 'promise', 'xhr', 'renderers/canvas'];
|
||||
|
||||
['/tests/assets/jquery-1.6.2'].concat(window.location.search === "?selenium" ? ['/dist/html2canvas'] : sources.map(function(src) { return '/src/' + src; })).forEach(appendScript);
|
||||
|
||||
appendScript('/dist/html2canvas.svg');
|
||||
|
||||
window.onload = function() {
|
||||
(function( $ ){
|
||||
$.fn.html2canvas = function(options) {
|
||||
|
Loading…
Reference in New Issue
Block a user