Skip to content

Commit

Permalink
Add support for canvg in place of browser loading image to canvas
Browse files Browse the repository at this point in the history
Provides workaround for IE's SecurityException.
  • Loading branch information
Jephuff authored and exupero committed Nov 7, 2016
1 parent 2fbfff8 commit bf057e4
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 41 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,15 @@ If you want to use TypeScript, necessary [type definitions](https://github.com/m
- `width` - Specify the image's width. Defaults to the viewbox's width if given, or the element's non-percentage width, or the element's bounding box's width, or the element's CSS width, or the computed style's width, or 0.
- `encoderType` - A DOMString indicating the image format. The default type is image/png.
- `encoderOptions` - A Number between 0 and 1 indicating image quality. The default is 0.8
- `canvg` - If canvg is passed in, it will be used to write svg to canvas. This will allow support for Internet Explorer

### Testing

run tests with [tape](https://www.npmjs.com/package/tape)
```bash
npm test
```

## Support

Internet Explorer is not supported due to the `SecurityError` it throws when calling `toDataURL` on a canvas that's been written to.
Internet Explorer will only work if [canvg](https://github.com/canvg/canvg) is passed in, otherwise it will throw a `SecurityError` when calling `toDataURL` on a canvas that's been written to. [canvg](https://github.com/canvg/canvg) may have it's own issues with SVG support, so ensure you test the output after switching.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "save-svg-as-png",
"version": "1.0.3",
"version": "1.1.0",
"description": "Convert a browser SVG to PNG or dataUri",
"main": "saveSvgAsPng.js",
"scripts": {
Expand Down
103 changes: 64 additions & 39 deletions saveSvgAsPng.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@
return decodeURIComponent(data);
}

out$.svgAsDataUri = function(el, options, cb) {
out$.prepareSvg = function(el, options, cb) {
requireDomNode(el);

options = options || {};
Expand Down Expand Up @@ -199,8 +199,15 @@
defs.appendChild(s);
clone.insertBefore(defs, clone.firstChild);

var svg = doctype + outer.innerHTML;
var uri = 'data:image/svg+xml;base64,' + window.btoa(reEncode(svg));
if (cb) {
cb(outer.innerHTML, width, height);
}
});
}

out$.svgAsDataUri = function(el, options, cb) {
out$.prepareSvg(el, options, function(svg) {
var uri = 'data:image/svg+xml;base64,' + window.btoa(reEncode(doctype + svg));
if (cb) {
cb(uri);
}
Expand All @@ -214,43 +221,62 @@
options.encoderType = options.encoderType || 'image/png';
options.encoderOptions = options.encoderOptions || 0.8;

out$.svgAsDataUri(el, options, function(uri) {
var image = new Image();
image.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext('2d');
if(options && options.backgroundColor){
context.fillStyle = options.backgroundColor;
context.fillRect(0, 0, canvas.width, canvas.height);
}
context.drawImage(image, 0, 0);
var a = document.createElement('a'), png;
try {
png = canvas.toDataURL(options.encoderType, options.encoderOptions);
} catch (e) {
if ((typeof SecurityError !== 'undefined' && e instanceof SecurityError) || e.name == "SecurityError") {
console.error("Rendered SVG images cannot be downloaded in this browser.");
return;
} else {
throw e;
}
}
cb(png);
var convertToPng = function(src, w, h) {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = w;
canvas.height = h;

if(options.canvg) {
options.canvg(canvas, src);
} else {
context.drawImage(src, 0, 0);
}

if(options.backgroundColor){
context.globalCompositeOperation = 'destination-over';
context.fillStyle = options.backgroundColor;
context.fillRect(0, 0, canvas.width, canvas.height);
}
image.onerror = function() {
console.error(
'There was an error loading the data URI as an image on the following SVG\n',
window.atob(uri.slice(26)), '\n',
"Open the following link to see browser's diagnosis\n",
uri);

var png;
try {
png = canvas.toDataURL(options.encoderType, options.encoderOptions);
} catch (e) {
if ((typeof SecurityError !== 'undefined' && e instanceof SecurityError) || e.name == "SecurityError") {
console.error("Rendered SVG images cannot be downloaded in this browser.");
return;
} else {
throw e;
}
}
image.src = uri;
});
cb(png);
}

if(options.canvg) {
out$.prepareSvg(el, options, convertToPng);
} else {
out$.svgAsDataUri(el, options, function(uri) {
var image = new Image();

image.onload = function() {
convertToPng(image, image.width, image.height);
}

image.onerror = function() {
console.error(
'There was an error loading the data URI as an image on the following SVG\n',
window.atob(uri.slice(26)), '\n',
"Open the following link to see browser's diagnosis\n",
uri);
}

image.src = uri;
});
}
}

function download(name, uri) {
out$.download = function(name, uri) {
if (navigator.msSaveOrOpenBlob) {
navigator.msSaveOrOpenBlob(uriToBlob(uri), name);
} else {
Expand All @@ -269,7 +295,6 @@
}
}
}
out$.download = download;

function uriToBlob(uri) {
var byteString = window.atob(uri.split(',')[1]);
Expand All @@ -287,7 +312,7 @@

options = options || {};
out$.svgAsDataUri(el, options, function(uri) {
download(name, uri);
out$.download(name, uri);
});
}

Expand All @@ -296,7 +321,7 @@

options = options || {};
out$.svgAsPngUri(el, options, function(uri) {
download(name, uri);
out$.download(name, uri);
});
}

Expand Down
3 changes: 3 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ test('Is loadable using requirejs', function (assert) {
'svgAsDataUri': 'function',
'svgAsPngUri': 'function',
'saveSvgAsPng': 'function',
'download': 'function',
'prepareSvg': 'function',
'saveSvg': 'function',
};

for (var property in saveSvgAsPng) {
Expand Down

0 comments on commit bf057e4

Please sign in to comment.