1 | <!DOCTYPE html>
|
2 | <meta http-equiv="content-type" content="text/html; charset=UTF8">
|
3 | <title>saveSvgAsPng</title>
|
4 |
|
5 | <link href='https://fonts.googleapis.com/css?family=Open+Sans:400italic,400,300,600' rel='stylesheet' type='text/css' />
|
6 | <link rel=stylesheet href=bootstrap.min.css />
|
7 | <style>
|
8 | @font-face {
|
9 | font-family: 'Stalemate';
|
10 | font-style: normal;
|
11 | font-weight: 400;
|
12 | src: url(stalemate.ttf) format('truetype');
|
13 | }
|
14 |
|
15 | input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button {
|
16 | padding: 15px;
|
17 | }
|
18 |
|
19 | h2, h3 {
|
20 | margin-top: 0;
|
21 | }
|
22 |
|
23 | h3 .btn {
|
24 | margin-top: -8px;
|
25 | }
|
26 |
|
27 | ul {
|
28 | list-style-type: none;
|
29 | padding: 0;
|
30 | }
|
31 |
|
32 | ul li {
|
33 | padding: 30px 20px;
|
34 | border-bottom: 1px dashed gray;
|
35 | }
|
36 |
|
37 | svg, img {
|
38 | border: 1px solid lightgray;
|
39 | }
|
40 |
|
41 | textarea {
|
42 | width: 100%;
|
43 | height: 100px;
|
44 | }
|
45 |
|
46 | .error {
|
47 | border: 1px solid red;
|
48 | border-radius: 10px;
|
49 | color: red;
|
50 | padding: 8px 10px;
|
51 | }
|
52 |
|
53 | #sized-with-css svg {
|
54 | width: 200px;
|
55 | height: 200px;
|
56 | }
|
57 |
|
58 | #selectors-prefixed svg rect {
|
59 | fill: blue;
|
60 | }
|
61 |
|
62 | rect.css-styled {
|
63 | fill: green !important;
|
64 | }
|
65 |
|
66 | #selectors-prefixed rect.css-styled {
|
67 | fill: green !important;
|
68 | }
|
69 |
|
70 |
|
71 |
|
72 | [ng\:cloak] {
|
73 | display: block;
|
74 | }
|
75 |
|
76 | ng\:form {
|
77 | display: block;
|
78 | }
|
79 | </style>
|
80 |
|
81 | <script type=text/template id=inline-template>
|
82 | <div class=row>
|
83 | <div class=col-md-6>
|
84 | <h2></h2>
|
85 | </div>
|
86 |
|
87 | <div class=col-md-6>
|
88 | <h3>Preview <button class="save btn">Save as PNG</button></h3>
|
89 | </div>
|
90 | </div>
|
91 |
|
92 | <div class=row>
|
93 | <div class="canvas col-md-6">
|
94 | </div>
|
95 |
|
96 | <div class=col-md-6>
|
97 | <div class=preview></div>
|
98 | </div>
|
99 | </div>
|
100 | </script>
|
101 |
|
102 | <div class=container>
|
103 |
|
104 |
|
105 | <span style='font-family: "Stalemate";color:white'>A</span>
|
106 | <h1>saveSvgAsPng</h1>
|
107 | <p>This page tests various features of saveSvgAsPng.</p>
|
108 | <p>You can test your own SVG code in the Sandbox. If something doesn't work as expected, you can <a href="https://github.com/exupero/saveSvgAsPng/issues">file an issue on GitHub</a>.</p>
|
109 |
|
110 | <ul>
|
111 | <li id=sandbox>
|
112 | <h2>Sandbox</h2>
|
113 | <p>Paste you SVG below to see how it renders.</p>
|
114 |
|
115 | <textarea><svg></svg></textarea>
|
116 | <br/>
|
117 | <button class="render btn">Preview</button>
|
118 | <div class=load-target style="margin-top:20px;"></div>
|
119 |
|
120 | <br/>
|
121 | <h3>Preview <button class="save btn">Save as PNG</button></h3>
|
122 | <span class=error style="display:none;"></span>
|
123 | <div class=preview></div>
|
124 | </li>
|
125 |
|
126 | <li id=filereader>
|
127 | <div class=row>
|
128 | <div class=col-md-6>
|
129 | <h2>Load from your hard drive</h2>
|
130 | </div>
|
131 |
|
132 | <div class=col-md-6>
|
133 | <h3>Preview <button class="save btn">Save as PNG</button></h3>
|
134 | </div>
|
135 | </div>
|
136 |
|
137 | <div class=row>
|
138 | <div class=col-md-6>
|
139 | <input type=file id=file name="files[]" />
|
140 | <div class=load-target></div>
|
141 | </div>
|
142 |
|
143 | <div class=col-md-6>
|
144 | <div class=preview>No file selected.</div>
|
145 | </div>
|
146 | </div>
|
147 | </li>
|
148 |
|
149 | <li id=inline>
|
150 | <svg width=200 height=200>
|
151 | <rect x=50 y=50 width=100 height=100></rect>
|
152 | </svg>
|
153 | </li>
|
154 |
|
155 | <li id=embedded-png>
|
156 | <svg width=200 height=200>
|
157 | <image xlink:href=image.png x=50 y=50 width=100 height=100></image>
|
158 | </svg>
|
159 | </li>
|
160 |
|
161 | <li id=embedded-svg>
|
162 | <svg width=200 height=200>
|
163 | <image xlink:href=test.svg x=50 y=50 width=100 height=100></image>
|
164 | </svg>
|
165 | </li>
|
166 |
|
167 | <li id=sized-with-pixels>
|
168 | <svg width="200px" height="200px">
|
169 | <rect x=50 y=50 width=100 height=100></rect>
|
170 | </svg>
|
171 | </li>
|
172 |
|
173 | <li id=sized-with-style>
|
174 | <svg style="width:200px;height:200px;">
|
175 | <rect x=50 y=50 width=100 height=100></rect>
|
176 | </svg>
|
177 | </li>
|
178 |
|
179 | <li id=sized-with-css>
|
180 | <svg>
|
181 | <rect x=50 y=50 width=100 height=100></rect>
|
182 | </svg>
|
183 | </li>
|
184 |
|
185 | <li id=scaling>
|
186 | <svg width=200 height=200>
|
187 | <rect width=100 height=100></rect>
|
188 | <image xlink:href=image.png x=50 y=50 width=100 height=100></image>
|
189 | </svg>
|
190 | </li>
|
191 |
|
192 | <li id=selectors-prefixed>
|
193 | <svg width=200 height=200>
|
194 | <rect x=0 y=50 width=100 height=100></rect>
|
195 | <rect class=css-styled x=100 y=50 width=100 height=100></rect>
|
196 | </svg>
|
197 | </li>
|
198 |
|
199 | <li id=modified-style>
|
200 | <svg width=200 height=200>
|
201 | <rect x=0 y=50 width=100 height=100></rect>
|
202 | <rect class=css-styled x=100 y=50 width=100 height=100></rect>
|
203 | </svg>
|
204 | </li>
|
205 |
|
206 | <li id=modified-css>
|
207 | <svg width=200 height=200>
|
208 | <rect x=0 y=50 width=100 height=100></rect>
|
209 | <rect class=css-styled x=100 y=50 width=100 height=100></rect>
|
210 | </svg>
|
211 | </li>
|
212 |
|
213 | <li id=group>
|
214 | <svg width=200 height=200>
|
215 | <g id=sub-group transform="translate(40,40)">
|
216 | <rect x=10 y=10 width=100 height=100></rect>
|
217 | </g>
|
218 | </svg>
|
219 | </li>
|
220 |
|
221 | <li id=percentage-size>
|
222 | <svg width="100%" height="100%">
|
223 | <rect x=25 y=25 width=100 height=100></rect>
|
224 | </svg>
|
225 | </li>
|
226 |
|
227 | <li id=background-color>
|
228 | <svg width=200 height=200>
|
229 | <g id=sub-group transform="translate(40,40)">
|
230 | <rect x=10 y=10 width=100 height=100></rect>
|
231 | </g>
|
232 | </svg>
|
233 | </li>
|
234 |
|
235 | <li id=pan-and-zoom>
|
236 | <svg width=200 height=200>
|
237 | <g transform="scale(2)">
|
238 | <rect x=10 y=10 width=100 height=100></rect>
|
239 | </g>
|
240 | </svg>
|
241 | </li>
|
242 |
|
243 | <li id=unicode>
|
244 | <svg width=200 height=200>
|
245 | <text x=100 y=100 text-anchor=middle dy=14>ö,i,ç,ğ</text>
|
246 | </svg>
|
247 | </li>
|
248 |
|
249 | <li id=gradient>
|
250 | <svg width=200 height=200>
|
251 | <defs>
|
252 | <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
|
253 | <stop offset="0%" style="stop-color:rgb(255,0,255);stop-opacity:1" />
|
254 | <stop offset="100%" style="stop-color:rgb(0,255,255);stop-opacity:1" />
|
255 | </linearGradient>
|
256 | </defs>
|
257 | <line x2="200" y2="200" stroke="url(#grad1)" stroke-width="5px" />
|
258 | </svg>
|
259 | </li>
|
260 |
|
261 | <li id=foreign-object>
|
262 | <svg width=200 height=200>
|
263 | <foreignobject x=50 y=50 width=50 height=100>
|
264 | <div>Foreign Object</div>
|
265 | </foreignobject>
|
266 | </svg>
|
267 | </li>
|
268 |
|
269 | <li id=xmlns-override>
|
270 | <svg width=200 height=200>
|
271 | <foreignobject x=50 y=50 width=50 height=100>
|
272 | <div xml:xmlns="http://www.w3.org/2000/xmlns/">Foreign Object</div>
|
273 | </foreignobject>
|
274 | </svg>
|
275 | </li>
|
276 |
|
277 | <li id=opacity>
|
278 | <svg width=200 height=200>
|
279 | <rect x=50 y=50 width=100 height=100 fill="green"></rect>
|
280 | <rect x=60 y=60 width=100 height=100 fill="blue" opacity="0.5"></rect>
|
281 | </svg>
|
282 | </li>
|
283 |
|
284 | <li id=entities>
|
285 | <svg width=200 height=200>
|
286 | <text x=50 y=100>"&¢ £»¼Ç</text>
|
287 | </svg>
|
288 | </li>
|
289 |
|
290 | <li id=transformed-text>
|
291 | <svg width=200 height=200>
|
292 | <text transform="translate(100,100)rotate(45)">Hello</text>
|
293 | </svg>
|
294 | </li>
|
295 |
|
296 | <li id=custom-font>
|
297 | <svg width=200 height=200>
|
298 | <text x=100 y=100 text-anchor=middle dy=14 style="font-family:'Stalemate';font-size:36pt;">Custom Fonts</text>
|
299 | </svg>
|
300 | <div style="color:red;">
|
301 | <p>
|
302 | Custom fonts are supported but in a very rudimentary way. Note: if you don't see the demo working,
|
303 | click "Save as PNG" - it should work.
|
304 | </p>
|
305 | <p>Make sure that the custom font is applied to a non-svg element first. This will help browser to rasterize SVG correctly onto canvas.</p>
|
306 | <p>@font-face declaration has to be inside document stylesheets (not in the external `link` tag)</p>
|
307 | <p>Only first `url()` is inlined into svg (don't have multiple urls in the font-face).</p>
|
308 | </div>
|
309 | </li>
|
310 | </ul>
|
311 | </div>
|
312 |
|
313 | <script src=https://code.jquery.com/jquery-latest.js></script>
|
314 | <script src=saveSvgAsPng.js></script>
|
315 | <script>
|
316 | function handleFileSelect(evt) {
|
317 | var $el = $('#filereader');
|
318 | var files = evt.target.files;
|
319 | for (var i = 0, f; f = files[i]; i++) {
|
320 | var reader = new FileReader();
|
321 | reader.onload = (function(file) {
|
322 | return function(e) {
|
323 | $el.find('.load-target').html(e.target.result);
|
324 | svgAsPngUri($el.find('.load-target svg')[0], null, function(uri) {
|
325 | $el.find('input').hide()
|
326 | $el.find('.preview').html('<img src="' + uri + '" />');
|
327 | });
|
328 | $el.find('.save').click(function() {
|
329 | saveSvgAsPng($el.find('.load-target svg')[0], 'test.png');
|
330 | });
|
331 | }
|
332 | })(f);
|
333 | reader.readAsText(f);
|
334 | }
|
335 | }
|
336 |
|
337 | if (window.File && window.FileReader && window.FileList && window.Blob) {
|
338 | document.getElementById('file').addEventListener('change', handleFileSelect, false);
|
339 | }
|
340 |
|
341 | function inlineTest(title, $el, saveOptions, testOptions) {
|
342 | var svg = $el.html();
|
343 | var template = $('#inline-template').html();
|
344 | var row = $el.html(template);
|
345 | row.find('h2').text(title);
|
346 | row.find('.canvas').html(svg);
|
347 |
|
348 | var canvas = row.find(testOptions && testOptions.selector || 'svg')[0];
|
349 | svgAsPngUri(canvas, saveOptions, function(uri) {
|
350 | row.find('.preview').html('<img src="' + uri + '" />');
|
351 | });
|
352 |
|
353 | row.find('.save').click(function() {
|
354 | saveSvgAsPng(canvas, 'test.png', saveOptions);
|
355 | });
|
356 | }
|
357 |
|
358 | inlineTest('Directly in the HTML', $('#inline'));
|
359 | inlineTest('With linked PNG image', $('#embedded-png'));
|
360 | inlineTest('With linked SVG image', $('#embedded-svg'));
|
361 | inlineTest('Sized with pixels', $('#sized-with-pixels'));
|
362 | inlineTest('Sized with style', $('#sized-with-style'));
|
363 | inlineTest('Sized with CSS', $('#sized-with-css'));
|
364 | inlineTest('At a higher resolution', $('#scaling'), {scale: 2});
|
365 | inlineTest('When CSS styling selectors are prefixed', $('#selectors-prefixed'), {
|
366 | selectorRemap: function(s) {return s.replace('#selectors-prefixed ', '')}
|
367 | });
|
368 | inlineTest('Modifying the style', $('#modified-style'), {
|
369 | modifyStyle: function(s) {return s.replace('green', 'red')}
|
370 | });
|
371 | inlineTest('Modifying the whole CSS rule', $('#modified-css'), {
|
372 | modifyCss: function(selector, properties) {
|
373 | selector = selector.replace('#selectors-prefixed ', '');
|
374 | properties = properties.replace('green', 'blue');
|
375 | return selector + '{' + properties + '}';
|
376 | }
|
377 | });
|
378 | inlineTest('Exporting a group within an SVG', $('#group'), null, {
|
379 | selector: '#sub-group'
|
380 | });
|
381 | inlineTest('Percentage Height and Width', $('#percentage-size'));
|
382 | inlineTest('Background color', $('#background-color'), {backgroundColor: 'lightblue'});
|
383 | inlineTest('Pan and Zoom', $('#pan-and-zoom'), {
|
384 | left: -50,
|
385 | top: -50,
|
386 | width: 300,
|
387 | height: 300
|
388 | });
|
389 | inlineTest('With Unicode characters', $('#unicode'));
|
390 | inlineTest('With gradients', $('#gradient'));
|
391 | inlineTest('With foreign objects', $('#foreign-object'));
|
392 | inlineTest('With opacity', $('#opacity'));
|
393 | inlineTest('When setting xmlns on foreign object children', $('#xmlns-override'));
|
394 | inlineTest('When using HTML entites', $('#entities'));
|
395 | inlineTest('Transformed text', $('#transformed-text'));
|
396 | inlineTest('With custom fonts', $('#custom-font'));
|
397 |
|
398 | var $sandbox = $('#sandbox');
|
399 | $sandbox.find('.render').click(function() {
|
400 | $sandbox.find('.error').hide().text('');
|
401 | $sandbox.find('.load-target').html($('#sandbox textarea').val());
|
402 | var canvas = $sandbox.find('.load-target svg')[0];
|
403 | try {
|
404 | svgAsPngUri(canvas, null, function(uri) {
|
405 | $sandbox.find('.preview').html('<img src="' + uri + '" />');
|
406 | });
|
407 | $sandbox.find('.save').unbind('click').click(function() {
|
408 | saveSvgAsPng(canvas, 'test.png');
|
409 | });
|
410 | } catch(err) {
|
411 | $sandbox.find('.error').show().text(err.message);
|
412 | $sandbox.find('.preview').html('');
|
413 | }
|
414 | });
|
415 | </script>
|