SVG'yi tarayıcıdaki görüntüye (JPEG, PNG vb.) Dönüştürün


300

SVG'yi JavaScript aracılığıyla bitmap görüntülere (JPEG, PNG, vb.) Dönüştürmek istiyorum.


Gerçekte hangi görevi yerine getirmek istiyorsunuz? Yankı akışları cevabı bize (bazı tarayıcılarda) mümkün olduğunu söylese de, neredeyse tüm pratik durumlar için daha iyi ve daha kolay dönüşüm yöntemleri vardır.
aaaaaaaaaaaa

2
İşte d3 kullanan bir örnek: stackoverflow.com/a/23667012/439699
ace

svgopen.org/2010/papers/62-From_SVG_to_Canvas_and_Back - Mükemmel çalışıyor! [Bağlantı sayfasında, sourceSVG = $ ("# your_svg_elem_name"). Get (0)]
Vijay Singh

Yanıtlar:


244

JavaScript ile nasıl yapabileceğiniz aşağıda açıklanmıştır:

  1. Tuval kullanarak SVG görüntüsünü oluşturmak için canvg JavaScript kitaplığını kullanın: https://github.com/gabelerner/canvg
  2. Tuvalden JPG (veya PNG) olarak kodlanmış bir veri URI'sini şu talimatlara göre yakalayın : HTML Kanvasını gif / jpg / png / pdf olarak yakalansın mı?

28
Bu kesinlikle Javascript değil, HTML5 de. Bu IE8 veya HTML5 Canvas'ı desteklemeyen başka bir tarayıcıda çalışmaz.
James

16
Tarayıcı SVG'yi ve tuvali destekliyorsa, SVG'yi belleğe yüklemenin ve daha sonra tuvalin içine boyamanın çok büyük bir yolu olurdu, bu da tüm SVG'yi ayrıştırdığı için oldukça büyük bir kütüphane olan Canvg'a ihtiyaç duymadan SVG destekli bir tarayıcı zaten ücretsiz sağlar. Bunun orijinal kullanım durumunu karşılayıp karşılamadığından emin değilim, ancak öyleyse ayrıntılar için bu kaynağa bakın .
Premasagar

120
IE8'i desteklemediğiniz için teşekkür ederiz. İnsanlar ilerlemenin zamanının geldiğini anlamalıdır.
Sanket Sahu

9
Artık bunu başarmak için JavaScript SVG kütüphanesi Pablo'yu kullanabilirsiniz. Otomatik olarak indirilen bir resim için toImage()ve bölümüne de bakın download().
Premasagar

2
svgopen.org/2010/papers/62-From_SVG_to_Canvas_and_Back - Mükemmel çalışıyor! [Bağlantı sayfasında, sourceSVG = $ ("# your_svg_elem_name"). Get (0)]
Vijay Singh

44

jbeard4 çözümü güzel çalıştı.

Bir SVG oluşturmak için Raphael SketchPad kullanıyorum . 1. adımdaki dosyalara bağlantı verin.

Kaydet düğmesi için (svg kimliği "düzenleyici", tuval kimliği "tuval" dir):

$("#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 ikinci parametre olması gerekiyor <svg>...</svgama jquery html () işlevi svg etiketi eklemeyin, bu yüzden bu kod benim için çalışıyor ama canvg canlı düzenlemek gerekiyorducanvg('canvas', '<svg>'+$("#editor").html()+'</svg>');
Luckyn

1
@Luckyn $(selector).html(), svg öğenizin ebeveynini ararsanız , işe yarayacak
jonathanGB

@Luckyn ve @jonathanGB, html()sarmalayıcılarda kullanmamalı veya üst svgetiketi manuel olarak oluşturmamalısınız - bu da bu kesmekle birlikte bırakabileceğiniz niteliklere sahip olabilir. Sadece kullanmak $(svg_elem)[0].outerHTMLsvg ve içeriğini tam kaynağı verir. Sadece söyleyerek ...
nemesisfixx

18

Bu, çoğu tarayıcıda işe yarıyor gibi görünüyor:

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
Bu güvenlik sorunu nedeniyle IE11'de çalışmıyor.msToBlob()
Florian Leitgeb

Teşekkürler!! Bunun "yerel" bir SVG HTML düğümü ve uzak bir SVG URL'si için nasıl çalıştığını seviyorum. Ayrıca tam bir harici kütüphane gerektirmez
Fabricio PH

7

SVG'yi blob URL'sine ve blob URL'sini png resmine dönüştürme çözümü

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

İşi yapan bu ES6 Sınıfını yazdım.

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;
  }
}

İşte nasıl kullanıyorsunuz

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.
});

Vanilya JavaScript sürümü istiyorsanız , Babel web sitesine gidip kodu oraya aktarabilirsiniz.


2

İşte PhantomJS tabanlı bir sunucu tarafı çözümü. Resim hizmetine etki alanları arası bir çağrı yapmak için JSONP'yi kullanabilirsiniz:

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

Örneğin:

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

Ardından img etiketi ile resim görüntüleyebilirsiniz:

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

Tarayıcıda çalışır.


Hizmet ölü gibi görünüyor.

3
Bizim ev sahibi sahte istekleri ile vurulmuştu. Bu yüzden onu indirmeye karar verdik. Şimdi kendi sunucunuzu çalıştırmanız gerekecek. Daha fazla bilgi için github repo'ya bakınız.
Phuoc

1

öğenize uygun svgşekilde değiştirin

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
benim için çalışmıyor, bu hatayı alıyorum:Uncaught TypeError: Failed to execute 'serializeToString' on 'XMLSerializer': parameter 1 is not of type 'Node'.
Xsmael

1
@Xsmael DOMParser arayüzünü değiştirmeye çalışın developer.mozilla.org/en-US/docs/Web/API/DOMParser
Mahdi Khalili

1

Svgiçin pngkoşullara bağlı olarak dönüştürülebilir:

  1. Eğer svgbiçiminde olan SVG (dize) yolları :
    • tuval oluştur
    • parametre olarak oluştur new Path2D()ve ayarlasvg
    • tuval üzerine yol çiz
    • Görüntüyü oluşturmak ve kullanmak canvas.toDataURL()olarak src.

misal:

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;

Not Path2Ddesteklenmeyen iekısmen kenar desteklenir. Çoklu doldurma bunu çözer: https://github.com/nilzona/path2d-polyfill

  1. svgKabarcık oluşturun ve aşağıdakileri kullanarak tuval üzerine çizim yapın .drawImage():
    • tuval elemanı yap
    • svg xml'den svgBlob nesnesi oluşturma
    • domUrl.createObjectURL (svgBlob) 'dan bir url nesnesi oluşturun;
    • bir Image nesnesi oluşturun ve resim src'sine url atayın
    • kanvasa resim çiz
    • tuvalden png veri dizesi alın: canvas.toDataURL ();

Güzel açıklama: http://ramblings.mcpher.com/Home/excelquirks/gassnips/svgtopng

Yani, canvas.toDataURL () aşamasında bir istisna alacağınızı unutmayın. IE çok yüksek güvenlik kısıtlaması vardır ve orada görüntü çizdikten sonra tuvali salt okunur gibi davranır. Diğer tüm tarayıcılar yalnızca görüntü çapraz orijinliyse kısıtlanır.

  1. canvgJavaScript kitaplığı kullanın . Ayrı bir kütüphanedir, ancak yararlı işlevlere sahiptir.

Sevmek:

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

3. bağlantı koptu
Serdar Sayın

Evet kesinlikle. Şimdi oraya nasıl ulaşacağımı bilmiyorum. Ancak yukarıdaki açıklama biraz anlayış için yeterli olabilir. Gelecekte işbirliği için iyi bir fikir referanstan sonra bazı bağlamları kopyalayın
Alex Vovchuk

0

Geçenlerde JavaScript için, hem boyut hem de kalite olmak üzere bitmap için kabul edilebilir bir yaklaşım oluşturabilen birkaç görüntü izleme kütüphanesi keşfettim. Bu JavaScript kitaplığını ve CLI'yi geliştiriyorum:

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

Tümü için birleşik API sağlar, DOM'a bağlı olmayan tarayıcı ve düğümü destekler ve bir Komut satırı aracı.

Logoları / çizgi film / benzeri görüntüleri dönüştürmek için mükemmel bir iş çıkarır. Fotoğraflar / gerçekçilik için, çıktı boyutu çok büyüyebileceğinden bazı ayarlamalar yapılması gerekiyor.

Bir oyun alanı var, ancak şu anda daha iyi bir özellik üzerinde çalışıyorum, kullanımı daha kolay, çünkü daha fazla özellik eklendi:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.