Конвертируем 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, я получил замечательную ошибку:
secureError
Дело в том, что 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. И получаем вот такой результат.

Надеюсь, статья окажется полезной для вас и сохранит ваше время.

ссылка на оригинал статьи http://habrahabr.ru/post/254973/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *