브라우저에서 SVG를 이미지 (JPEG, PNG 등)로 변환


299

SVG를 JavaScript를 통해 비트 맵 이미지 (JPEG, PNG 등)로 변환하고 싶습니다.


실제로 달성하고자하는 일은 무엇입니까? echo-flows 응답은 (일부 브라우저에서) 거의 모든 실제 사례에 대해 더 좋고 쉬운 변환 방법이 가능하다는 것을 알려줍니다.
aaaaaaaaaaaa

2
다음은 d3을 사용하는 예입니다. stackoverflow.com/a/23667012/439699
ace

svgopen.org/2010/papers/62-From_SVG_to_Canvas_and_Back- 완벽하게 작동합니다! [링크 페이지에서 sourceSVG = $ ( "# your_svg_elem_name"). get (0)]
Vijay Singh

답변:


244

JavaScript를 통해이를 수행하는 방법은 다음과 같습니다.

  1. 캔버스를 사용하여 SVG 이미지를 렌더링하려면 canvg JavaScript 라이브러리를 사용하십시오. https://github.com/gabelerner/canvg
  2. 다음 지침에 따라 캔버스에서 JPG (또는 PNG)로 인코딩 된 데이터 URI를 캡처하십시오. HTML 캔버스를 gif / jpg / png / pdf로 캡처 하시겠습니까?

28
이것은 엄격하게 자바 스크립트가 아니라 HTML5입니다. IE8 또는 HTML5 Canvas를 지원하지 않는 다른 브라우저에서는 작동하지 않습니다.
James

16
브라우저가 SVG와 캔버스를 지원하는 경우 SVG를 메모리에로드 한 다음 캔버스에 페인트하는 훨씬 간단한 방법이 있습니다. Canvg는 모든 SVG 구문 분석을 처리하기 때문에 매우 큰 라이브러리입니다. SVG 지원 브라우저는 이미 무료로 제공합니다. 이것이 원래의 유스 케이스를 충족시키는 지 확실하지 않지만 그렇다면 그렇다면 이 리소스를 참조하십시오 .
Premasagar

120
IE8을 지원하지 않아서 감사합니다. 사람들은 이제 나아가 야 할 때라는 것을 이해해야합니다.
Sanket Sahu

9
이제 JavaScript SVG 라이브러리 Pablo 를 사용하여이 작업을 수행 할 수 있습니다 (제작했습니다). 참고 항목 toImage()download()자동 다운로드 이미지.
Premasagar

2
svgopen.org/2010/papers/62-From_SVG_to_Canvas_and_Back- 완벽하게 작동합니다! [링크 페이지에서 sourceSVG = $ ( "# your_svg_elem_name"). get (0)]
Vijay Singh

44

jbeard4 솔루션은 아름답게 작동했습니다.

내가 사용하고 라파엘 스케치를 SVG를 만들 수 있습니다. 1 단계의 파일에 연결하십시오.

저장 버튼 (svg의 ID는 "editor", 캔버스의 id는 "canvas")의 경우 :

$("#editor_save").click(function() {

// the canvg call that takes the svg xml and converts it to a canvas
canvg('canvas', $("#editor").html());

// the canvas calls to output a png
var canvas = document.getElementById("canvas");
var img = canvas.toDataURL("image/png");
// do what you want with the base64, write to screen, post to server, etc...
});

1
canvg이 될 두 번째 매개 변수를 필요로 <svg>...</svg이 코드는 나를 위해 작동하지만 난에 canvg 라이브 편집에 필요한 있도록하지만, JQuery와 HTML () 함수는 SVG 태그를 추가하지 마십시오canvg('canvas', '<svg>'+$("#editor").html()+'</svg>');
Luckyn

1
당신이 호출하면 @Luckyn는 $(selector).html()당신의 부모에 SVG의 요소, 그것은 작동합니다
jonathanGB

@Luckyn과 @jonathanGB html()는 래퍼에서 사용하거나 수동으로 부모 svg태그를 구성 하지 않아도됩니다 . 그냥 사용 $(svg_elem)[0].outerHTML하면 svg와 그 내용의 전체 소스가 제공됩니다. 그냥 말하기
nemesisfixx

18

이것은 대부분의 브라우저에서 작동하는 것 같습니다.

function copyStylesInline(destinationNode, sourceNode) {
   var containerElements = ["svg","g"];
   for (var cd = 0; cd < destinationNode.childNodes.length; cd++) {
       var child = destinationNode.childNodes[cd];
       if (containerElements.indexOf(child.tagName) != -1) {
            copyStylesInline(child, sourceNode.childNodes[cd]);
            continue;
       }
       var style = sourceNode.childNodes[cd].currentStyle || window.getComputedStyle(sourceNode.childNodes[cd]);
       if (style == "undefined" || style == null) continue;
       for (var st = 0; st < style.length; st++){
            child.style.setProperty(style[st], style.getPropertyValue(style[st]));
       }
   }
}

function triggerDownload (imgURI, fileName) {
  var evt = new MouseEvent("click", {
    view: window,
    bubbles: false,
    cancelable: true
  });
  var a = document.createElement("a");
  a.setAttribute("download", fileName);
  a.setAttribute("href", imgURI);
  a.setAttribute("target", '_blank');
  a.dispatchEvent(evt);
}

function downloadSvg(svg, fileName) {
  var copy = svg.cloneNode(true);
  copyStylesInline(copy, svg);
  var canvas = document.createElement("canvas");
  var bbox = svg.getBBox();
  canvas.width = bbox.width;
  canvas.height = bbox.height;
  var ctx = canvas.getContext("2d");
  ctx.clearRect(0, 0, bbox.width, bbox.height);
  var data = (new XMLSerializer()).serializeToString(copy);
  var DOMURL = window.URL || window.webkitURL || window;
  var img = new Image();
  var svgBlob = new Blob([data], {type: "image/svg+xml;charset=utf-8"});
  var url = DOMURL.createObjectURL(svgBlob);
  img.onload = function () {
    ctx.drawImage(img, 0, 0);
    DOMURL.revokeObjectURL(url);
    if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob)
    {
        var blob = canvas.msToBlob();         
        navigator.msSaveOrOpenBlob(blob, fileName);
    } 
    else {
        var imgURI = canvas
            .toDataURL("image/png")
            .replace("image/png", "image/octet-stream");
        triggerDownload(imgURI, fileName);
    }
    document.removeChild(canvas);
  };
  img.src = url;
}

3
IE11에서는 작동하지 않습니다..msToBlob()
Florian Leitgeb

감사!! "로컬"SVG HTML 노드와 원격 SVG URL 모두에서 이것이 작동하는 방식을 좋아합니다. 또한 완전한 외부 라이브러리가 필요하지 않습니다
Fabricio PH

7

SVG를 BLOB URL로 변환하고 BLOB URL을 PNG 이미지로 변환하는 솔루션

const svg=`<svg version="1.1" baseProfile="full" width="300" height="200"
xmlns="http://www.w3.org/2000/svg">
   <rect width="100%" height="100%" fill="red" />
   <circle cx="150" cy="100" r="80" fill="green" />
   <text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text></svg>`
svgToPng(svg,(imgData)=>{
    const pngImage = document.createElement('img');
    document.body.appendChild(pngImage);
    pngImage.src=imgData;
});
 function svgToPng(svg, callback) {
    const url = getSvgUrl(svg);
    svgUrlToPng(url, (imgData) => {
        callback(imgData);
        URL.revokeObjectURL(url);
    });
}
function getSvgUrl(svg) {
    return  URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' }));
}
function svgUrlToPng(svgUrl, callback) {
    const svgImage = document.createElement('img');
    // imgPreview.style.position = 'absolute';
    // imgPreview.style.top = '-9999px';
    document.body.appendChild(svgImage);
    svgImage.onload = function () {
        const canvas = document.createElement('canvas');
        canvas.width = svgImage.clientWidth;
        canvas.height = svgImage.clientHeight;
        const canvasCtx = canvas.getContext('2d');
        canvasCtx.drawImage(svgImage, 0, 0);
        const imgData = canvas.toDataURL('image/png');
        callback(imgData);
        // document.body.removeChild(imgPreview);
    };
    svgImage.src = svgUrl;
 }


3

나는 일을하는이 ES6 클래스를 썼습니다.

class SvgToPngConverter {
  constructor() {
    this._init = this._init.bind(this);
    this._cleanUp = this._cleanUp.bind(this);
    this.convertFromInput = this.convertFromInput.bind(this);
  }

  _init() {
    this.canvas = document.createElement("canvas");
    this.imgPreview = document.createElement("img");
    this.imgPreview.style = "position: absolute; top: -9999px";

    document.body.appendChild(this.imgPreview);
    this.canvasCtx = this.canvas.getContext("2d");
  }

  _cleanUp() {
    document.body.removeChild(this.imgPreview);
  }

  convertFromInput(input, callback) {
    this._init();
    let _this = this;
    this.imgPreview.onload = function() {
      const img = new Image();
      _this.canvas.width = _this.imgPreview.clientWidth;
      _this.canvas.height = _this.imgPreview.clientHeight;
      img.crossOrigin = "anonymous";
      img.src = _this.imgPreview.src;
      img.onload = function() {
        _this.canvasCtx.drawImage(img, 0, 0);
        let imgData = _this.canvas.toDataURL("image/png");
        if(typeof callback == "function"){
            callback(imgData)
        }
        _this._cleanUp();
      };
    };

    this.imgPreview.src = input;
  }
}

사용 방법은 다음과 같습니다.

let input = "https://restcountries.eu/data/afg.svg"
new SvgToPngConverter().convertFromInput(input, function(imgData){
    // You now have your png data in base64 (imgData). 
    // Do what ever you wish with it here.
});

바닐라 JavaScript 버전을 원한다면 Babel 웹 사이트 로 가서 코드를 번역하십시오.


2

다음은 PhantomJS 기반 서버 측 솔루션입니다. JSONP를 사용하여 이미지 서비스에 대한 도메인 간 호출을 수행 할 수 있습니다.

https://github.com/vidalab/banquo-server

예를 들면 다음과 같습니다.

http : // [host] /api/https%3A%2F%2Fvida.io%2Fdocuments%2FWgBMc4zDWF7YpqXGR/viewport_width=980&viewport_height=900&delay=5000&selector=%23canvas

그런 다음 img 태그를 사용하여 이미지를 표시 할 수 있습니다.

<img src="data:image/png;base64, [base64 data]"/>

브라우저에서 작동합니다.


서비스가 종료 된 것 같습니다.

3
우리 호스트는 가짜 요청에 부딪쳤다. 그래서 우리는 그것을 중단하기로 결정했습니다. 지금 당신은 당신의 자신의 서버를 실행해야합니다. 자세한 내용은 github repo를 참조하십시오.
Phuoc Do

1

svg요소와 일치하도록 변경

function svg2img(){
    var svg = document.querySelector('svg');
    var xml = new XMLSerializer().serializeToString(svg);
    var svg64 = btoa(xml); //for utf8: btoa(unescape(encodeURIComponent(xml)))
    var b64start = 'data:image/svg+xml;base64,';
    var image64 = b64start + svg64;
    return image64;
};svg2img()

1
그것은 나를 위해 작동하지 않습니다, 나는이 오류가 발생합니다 :Uncaught TypeError: Failed to execute 'serializeToString' on 'XMLSerializer': parameter 1 is not of type 'Node'.
Xsmael

1
DOMParser 인터페이스로 전환하려고 @Xsmael developer.mozilla.org/en-US/docs/Web/API/DOMParser을
마흐디 칼 릴리에게

1

Svg에이 png조건에 따라 변환 할 수 있습니다 :

  1. SVG (문자열) 경로svg 형식 인 경우 :
    • 캔버스 만들기
    • 매개 변수로 작성 new Path2D()및 설정svg
    • 캔버스에 패스 그리기
    • 이미지를 생성하고 사용 canvas.toDataURL()으로 src.

예:

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
let svgText = 'M10 10 h 80 v 80 h -80 Z';
let p = new Path2D('M10 10 h 80 v 80 h -80 Z');
ctx.stroke(p);
let url = canvas.toDataURL();
const img = new Image();
img.src = url;

그 주 Path2D에서 지원되지 ie부분적 가장자리에서 지원. Polyfill이이를 해결합니다 : https://github.com/nilzona/path2d-polyfill

  1. 다음을 svg사용하여 Blob을 만들고 캔버스에 그립니다 .drawImage().
    • 캔버스 요소 만들기
    • svg xml에서 svgBlob 객체 만들기
    • domUrl.createObjectURL (svgBlob)에서 URL 객체를 만듭니다.
    • 이미지 객체를 만들고 이미지 src에 URL을 할당하십시오.
    • 캔버스에 이미지를 그리다
    • 캔버스에서 png 데이터 문자열을 가져옵니다. canvas.toDataURL ();

좋은 설명 : http://ramblings.mcpher.com/Home/excelquirks/gassnips/svgtopng

즉, canvas.toDataURL ()의 단계에서 예외가 발생합니다. IE는 보안 제한이 너무 높고 이미지를 그린 후 캔버스를 읽기 전용으로 취급하기 때문입니다. 다른 모든 브라우저는 이미지가 교차 출처 인 경우에만 제한합니다.

  1. canvgJavaScript 라이브러리를 사용하십시오 . 별도의 라이브러리이지만 유용한 기능이 있습니다.

처럼:

ctx.drawSvg(rawSvg);
var dataURL = canvas.toDataURL();

세 번째 링크가 끊어짐
Serdar Sayın

네 확실합니다. 나는 지금 거기에 도달하는 방법을 모른다. 그러나 위의 설명은 이해하기에 충분할 수 있습니다. 향후 공동 참조를위한 좋은 아이디어 참조 후 일부 컨텍스트 복사
Alex Vovchuk

0

최근에 크기와 품질 모두 비트 맵에 대해 적절한 근사치를 만들 수있는 JavaScript 용 이미지 추적 라이브러리 두 개를 발견했습니다. 이 JavaScript 라이브러리와 CLI를 개발 중입니다.

https://www.npmjs.com/package/svg-png-converter

DOM에 의존하지 않고 브라우저와 노드를 지원하고 명령 줄 도구를 지원하는 통합 API를 제공합니다.

로고 / 만화 / 유사 이미지를 변환하는 데 탁월한 성능을 발휘합니다. 사진 / 현실주의의 경우 출력 크기가 많이 커질 수 있으므로 약간의 조정이 필요합니다.

더 많은 기능이 추가되었으므로 지금은 더 나은 작업을하고 더 사용하기 쉬운 놀이터가 있습니다.

https://cancerberosgx.github.io/demos/svg-png-converter/playground/#

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.