Конвертируем svg to png
Иногда появляется необходимость сохранить svg в png средствами браузера. К сожалению, браузер не имеет волшебного api, который позволил бы это сделать без различных хаков. Что же делать, если все таки хочется добиться желаемого? Первая идея, которая мне пришла в голову, сделать это через canvas, который имеет метод toDataURL ('image/png'); Итак, я написал простенький скрипт: jsfiddle, github: var html = document.querySelector («svg»).parentNode.innerHTML; var imgsrc = 'data: image/svg+xml; base64,' + btoa (html); var canvas = document.querySelector («canvas»), context = canvas.getContext (»2d»); canvas.setAttribute ('width', 526); canvas.setAttribute ('height', 233);
var image = new Image; image.src = imgsrc; image.onload = function () { context.drawImage (image, 0, 0); var canvasdata = canvas.toDataURL («image/png»); var a = document.createElement («a»); a.textContent = «save»; a.download = «export_» + Date.now () + ».png»; a.href = canvasdata; document.body.appendChild (a); canvas.parentNode.removeChild (canvas); }; Суть скрипта проста: я преобразовывал svg в dataUri, загружал его через image, рисовал картинку на canvas и превращал в png. Казалось, цель достигнута, и можно расслабится. Этот подход сработал в Firefox и Chrome, но открыв во всеми нами любимом браузере IE, я получил замечательную ошибку: Дело в том, что IE считает, что картинка загружена с другого хоста. К сожалению, установить origin для dataUri не получится. Собственно, описание правил можно найти здесь: https://html.spec.whatwg.org/multipage/scripting.html#security-with-canvas-elements. Можно было, конечно, проксировать svg через сервер, и тогда все бы сработало, но хотелось чисто клиентское решение.
И тут я вспомнил про замечательную библиотеку canvg. С помощью этой библиотеки я рисую svg на canvas, а далее поступаю как в первом варианте: беру toDataURL («image/png»). Получился такой незамысловатый код: github:
var svg = document.querySelector ('svg'); var canvas = document.createElement ('canvas'); canvas.height = svg.getAttribute ('height'); canvas.width = svg.getAttribute ('width'); canvg (canvas, svg.parentNode.innerHTML.trim ()); var dataURL = canvas.toDataURL ('image/png'); var data = atob (dataURL.substring ('data: image/png; base64,'.length)), asArray = new Uint8Array (data.length);
for (var i = 0, len = data.length; i < len; ++i) { asArray[i] = data.charCodeAt(i); }
var blob = new Blob ([asArray.buffer], {type: 'image/png'}); saveAs (blob, 'export_' + Date.now () + '.png'); Тут стоит сказать, что еще я использовал библиотеку FileSaver для вызова диалогового окна сохранения.Вот и все, мы добились желаемого результата.
Стоит отметить один нюанс — я задался вопросом сохранения svg в png, когда писал плагин для экспорта tauCharts. Так как стили в svg задаются из внешнего файла, чтобы добиться максимально подобия с исходным svg, я вставляю inline style в svg. И получаем вот такой результат.
Надеюсь, статья окажется полезной для вас и сохранит ваше время.