├── README.md
├── base64.js
├── butterfly_test.html
├── index.js
└── package.json
/README.md:
--------------------------------------------------------------------------------
1 | SVG.toDataURL()
2 | ===============
3 |
4 | The missing `SVG.toDataURL()` for your SVG elements. Supports exporting as SVG+XML and PNG.
5 |
6 | See [original paper][svgopen2010] for more information on interfacing between SVG and Canvas.
7 |
8 | Instructions
9 | ------------
10 |
11 | 1. Include [canvg] if you need PNG support for unsupported browers (see compatibility below).
12 | 2. ``
13 | 3. See `butterfly_test.html` for full example & compability test.
14 |
15 | ```javascript
16 | mySVGelement.toDataURL("image/png", {
17 | callback: function(data) {
18 | myIMGelement.setAttribute("src", data)
19 | }
20 | })
21 | ```
22 |
23 | API documentation inside [svg_todataurl.js](svg_todataurl.js).
24 |
25 | Compatibility
26 | -------------
27 |
28 | Test your browser with our [butterfly test suite](http://sampumon.github.io/SVG.toDataURL/butterfly_test.html).
29 |
30 | Works in all modern browsers. Some browsers require [canvg] for PNG exporting.
31 |
32 | Compatibility as of October 2017. `+` yes, `vv+` yes since version vv, `-` no support yet.
33 |
34 | Browser E x p o r t i n g f o r m a t
35 | SVG+XML PNG/canvg PNG/native
36 | IE 9+ 9+ edge
37 | Chrome + + 33+ ²
38 | Safari + + 7.1+ ³
39 | Firefox + + 11+ ¹
40 | Opera + + +
41 |
42 | ¹ [Allow SVG-as-an-image to be drawn into a canvas without marking it as write-only](https://bugzilla.mozilla.org/show_bug.cgi?id=672013)
43 | ² [Implement SVGImage::hasSingleSecurityOrigin()](https://bugs.webkit.org/show_bug.cgi?id=119492)
44 | ³ [Test Browser Support for SVG to Canvas](http://designashirt.github.io/svg-canvas-tests/)
45 |
46 | Notes
47 | -----
48 |
49 | * SVG `` elements only work if their `src` is a dataURL. External images, same domain or not, will not be rendered (but won't cause a security exception either).
50 |
51 | Final
52 | -----
53 |
54 | Licensed with the permissive MIT license, as follows.
55 |
56 | Copyright (c) 2010,2012 Sampu-mon & Mat-san
57 |
58 | Permission is hereby granted, free of charge, to any person obtaining a copy
59 | of this software and associated documentation files (the "Software"), to deal
60 | in the Software without restriction, including without limitation the rights
61 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
62 | copies of the Software, and to permit persons to whom the Software is
63 | furnished to do so, subject to the following conditions:
64 |
65 | The above copyright notice and this permission notice shall be included in
66 | all copies or substantial portions of the Software.
67 |
68 | [canvg]:http://code.google.com/p/canvg/
69 | [svgopen2010]:http://svgopen.org/2010/papers/62-From_SVG_to_Canvas_and_Back/
70 |
--------------------------------------------------------------------------------
/base64.js:
--------------------------------------------------------------------------------
1 | // http://www.webtoolkit.info/javascript-base64.html
2 |
3 | var Base64 = {
4 |
5 | // private property
6 | _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
7 |
8 | // public method for encoding
9 | encode : function (input) {
10 | var output = "";
11 | var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
12 | var i = 0;
13 |
14 | input = Base64._utf8_encode(input);
15 |
16 | while (i < input.length) {
17 |
18 | chr1 = input.charCodeAt(i++);
19 | chr2 = input.charCodeAt(i++);
20 | chr3 = input.charCodeAt(i++);
21 |
22 | enc1 = chr1 >> 2;
23 | enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
24 | enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
25 | enc4 = chr3 & 63;
26 |
27 | if (isNaN(chr2)) {
28 | enc3 = enc4 = 64;
29 | } else if (isNaN(chr3)) {
30 | enc4 = 64;
31 | }
32 |
33 | output = output +
34 | this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
35 | this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
36 |
37 | }
38 |
39 | return output;
40 | },
41 |
42 | // public method for decoding
43 | decode : function (input) {
44 | var output = "";
45 | var chr1, chr2, chr3;
46 | var enc1, enc2, enc3, enc4;
47 | var i = 0;
48 |
49 | input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
50 |
51 | while (i < input.length) {
52 |
53 | enc1 = this._keyStr.indexOf(input.charAt(i++));
54 | enc2 = this._keyStr.indexOf(input.charAt(i++));
55 | enc3 = this._keyStr.indexOf(input.charAt(i++));
56 | enc4 = this._keyStr.indexOf(input.charAt(i++));
57 |
58 | chr1 = (enc1 << 2) | (enc2 >> 4);
59 | chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
60 | chr3 = ((enc3 & 3) << 6) | enc4;
61 |
62 | output = output + String.fromCharCode(chr1);
63 |
64 | if (enc3 != 64) {
65 | output = output + String.fromCharCode(chr2);
66 | }
67 | if (enc4 != 64) {
68 | output = output + String.fromCharCode(chr3);
69 | }
70 |
71 | }
72 |
73 | output = Base64._utf8_decode(output);
74 |
75 | return output;
76 |
77 | },
78 |
79 | // private method for UTF-8 encoding
80 | _utf8_encode : function (string) {
81 | string = string.replace(/\r\n/g,"\n");
82 | var utftext = "";
83 |
84 | for (var n = 0; n < string.length; n++) {
85 |
86 | var c = string.charCodeAt(n);
87 |
88 | if (c < 128) {
89 | utftext += String.fromCharCode(c);
90 | }
91 | else if((c > 127) && (c < 2048)) {
92 | utftext += String.fromCharCode((c >> 6) | 192);
93 | utftext += String.fromCharCode((c & 63) | 128);
94 | }
95 | else {
96 | utftext += String.fromCharCode((c >> 12) | 224);
97 | utftext += String.fromCharCode(((c >> 6) & 63) | 128);
98 | utftext += String.fromCharCode((c & 63) | 128);
99 | }
100 |
101 | }
102 |
103 | return utftext;
104 | },
105 |
106 | // private method for UTF-8 decoding
107 | _utf8_decode : function (utftext) {
108 | var string = "";
109 | var i = 0;
110 | var c = c1 = c2 = 0;
111 |
112 | while ( i < utftext.length ) {
113 |
114 | c = utftext.charCodeAt(i);
115 |
116 | if (c < 128) {
117 | string += String.fromCharCode(c);
118 | i++;
119 | }
120 | else if((c > 191) && (c < 224)) {
121 | c2 = utftext.charCodeAt(i+1);
122 | string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
123 | i += 2;
124 | }
125 | else {
126 | c2 = utftext.charCodeAt(i+1);
127 | c3 = utftext.charCodeAt(i+2);
128 | string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
129 | i += 3;
130 | }
131 |
132 | }
133 |
134 | return string;
135 | }
136 |
137 | }
138 |
--------------------------------------------------------------------------------
/butterfly_test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SVG.toDataURL butterfly test
6 |
7 |
8 |
9 |
10 |
13 |
14 |
18 |
19 |
20 |
21 |
36 |
37 |
53 |
54 |
55 |
56 |
57 | The SVG butterfly.
58 | If a second butterfly appears when pressing button, native SVG.toDataURL works in your browser. Check console for details.
59 |
64 |
65 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | The missing SVG.toDataURL library for your SVG elements.
3 |
4 | Usage: SVGElement.toDataURL( type, { options } )
5 |
6 | Returns: the data URL, except when using native PNG renderer (needs callback).
7 |
8 | type MIME type of the exported data.
9 | Default: image/svg+xml.
10 | Must support: image/png.
11 | Additional: image/jpeg.
12 |
13 | options is a map of options: {
14 | callback: function(dataURL)
15 | Callback function which is called when the data URL is ready.
16 | This is only necessary when using native PNG renderer.
17 | Default: undefined.
18 |
19 | [the rest of the options only apply when type="image/png" or type="image/jpeg"]
20 |
21 | renderer: "native"|"canvg"
22 | PNG renderer to use. Native renderer¹ might cause a security exception.
23 | Default: canvg if available, otherwise native.
24 |
25 | keepNonSafe: true|false
26 | Export non-safe (image and foreignObject) elements.
27 | This will set the Canvas origin-clean property to false, if this data is transferred to Canvas.
28 | Default: false, to keep origin-clean true.
29 | NOTE: not currently supported and is just ignored.
30 |
31 | keepOutsideViewport: true|false
32 | Export all drawn content, even if not visible.
33 | Default: false, export only visible viewport, similar to Canvas toDataURL().
34 | NOTE: only supported with canvg renderer.
35 | }
36 |
37 | See original paper¹ for more info on SVG to Canvas exporting.
38 |
39 | ¹ http://svgopen.org/2010/papers/62-From_SVG_to_Canvas_and_Back/#svg_to_canvas
40 | */
41 |
42 | module.exports = function toDataURL(_svg, type, options) {
43 | function defaultDebug(s) {
44 | console.log("SVG.toDataURL:", s);
45 | }
46 | var debug = options && options.debug ? options.debug : defaultDebug;
47 | var myCanvg = options && options.canvg ? options.canvg : typeof canvg === 'function' ? canvg : window.canvg;
48 |
49 | function exportSVG() {
50 | var svg_xml = XMLSerialize(_svg);
51 | var svg_dataurl = base64dataURLencode(svg_xml);
52 | debug(type + " length: " + svg_dataurl.length);
53 |
54 | // NOTE double data carrier
55 | if (options.callback) options.callback(svg_dataurl);
56 | return svg_dataurl;
57 | }
58 |
59 | function XMLSerialize(svg) {
60 |
61 | // quick-n-serialize an SVG dom, needed for IE9 where there's no XMLSerializer nor SVG.xml
62 | // s: SVG dom, which is the