Как нарисовать встроенный SVG (в DOM) на холсте?

Ну, мне нужна помощь по преобразованию .svg файла/изображения в файл .png/image...

У меня есть изображение .svg, отображаемое на моей странице. Он сохраняется на моем сервере (в виде файла .png). Мне нужно преобразовать его в файл .png по требованию (при нажатии на кнопку) и сохранить файл .png на сервере (я сделаю это с помощью запроса .ajax).

Но проблема заключается в преобразовании.

Я читал много вещей о холсте html5, который, вероятно, может помочь сделать то, что мне нужно сделать сейчас, но я не могу найти четкое решение моей проблемы, и, tbh, я не понимаю все, что нашел. Поэтому мне нужны четкие советы/помощь о том, как я должен это делать.

Вот шаблон шаблона html:

<html>
    <body>
        <svg id="mySvg" width="300px" height="300px">
            <!-- my svg data -->
        </svg>
        <label id="button">Click to convert</label>
        <canvas id="myCanvas"></canvas>
    </body>
</html>

и некоторые js:

<script>
    $("body").on("click","#button",function(){
        var svgText = $("#myViewer").outerHTML;
        var myCanvas = document.getElementById("canvas");
        var ctxt = myCanvas.getContext("2d");
    });
</script>

Затем мне нужно нарисовать svg в Canvas, вернуть данные base64 и сохранить его в .png файле на моем сервере... но... как? Я читал о многих разных решениях, которые я на самом деле... потерял... Я работаю над jsfiddle, но я на самом деле... нигде... http://jsfiddle.net/xfh7nctk/6/... Спасибо за чтение/помощь

Ответ 1

Для встроенного SVG вам необходимо:

  • Преобразовать строку SVG в Blob
  • Получить URL для BLOB-объекта
  • Создайте элемент изображения и установите URL-адрес как src
  • При загрузке (onload) вы можете нарисовать SVG как изображение на холсте
  • Используйте toDataURL(), чтобы получить файл PNG с холста.

Например:

function drawInlineSVG(ctx, rawSVG, callback) {

    var svg = new Blob([rawSVG], {type:"image/svg+xml;charset=utf-8"}),
        domURL = self.URL || self.webkitURL || self,
        url = domURL.createObjectURL(svg),
        img = new Image;

    img.onload = function () {
        ctx.drawImage(this, 0, 0);     
        domURL.revokeObjectURL(url);
        callback(this);
    };

    img.src = url;
}

// usage:
drawInlineSVG(ctxt, svgText, function() {
    console.log(canvas.toDataURL());  // -> PNG data-uri
});

Конечно, console.log здесь только для примера. Вместо этого сохраните/перенесите строку. (Я бы также рекомендовал добавить обработчик onerror внутри метода).

Также не забудьте установить размер холста, используя атрибуты width и height, или из JavaScript, используя свойства.

Ответ 2

Я нахожусь уже после того, как возникает другой вопрос, связанный с этим, потому что принятый ответ может вызвать нежелательное поведение.

Решение

@K3N почти правильно, но я бы пошел против использования svgElement.outerHTML.
Вместо этого следует предпочесть new XMLSerializer().serializeToString(svgElement).

Кроме того, использование blob и URL API не требуется, и простой dataURI имеет большую совместимость по сравнению с браузерами.

Таким образом, полная версия:

function drawInlineSVG(svgElement, ctx, callback){
  var svgURL = new XMLSerializer().serializeToString(svgElement);
  var img  = new Image();
  img.onload = function(){
    ctx.drawImage(this, 0,0);
    callback();
    }
  img.src = 'data:image/svg+xml; charset=utf8, '+encodeURIComponent(svgURL);
  }

//usage :
drawInlineSVG(document.querySelector('svg'), ctxt, function(){console.log(canvas.toDataURL())})