ब्राउज़र में SVG को इमेज (JPEG, PNG, आदि) में बदलें


299

मैं जावास्क्रिप्ट के माध्यम से एसवीजी को बिटमैप छवियों (जैसे जेपीईजी, पीएनजी, आदि) में बदलना चाहता हूं।


वह कौन सा कार्य है जिसे आप वास्तव में पूरा करना चाहते हैं? हालांकि इको-फ्लो उत्तर हमें बताते हैं कि यह (कुछ ब्राउज़रों में) संभव है कि लगभग सभी व्यावहारिक मामलों के लिए बेहतर और आसान रूपांतरण के तरीके हैं।
आआआआआआआआआआआआआआआआआआ आआआआआट


svgopen.org/2010/papers/62-From_SVG_to_Canvas_and_Back - पूरी तरह से काम करता है! [लिंक पेज पर, sourceSVG = $ ("# your_svg_elem_name"))। (0)]
विजय सिंह

जवाबों:


244

यहाँ आप इसे जावास्क्रिप्ट के माध्यम से कैसे कर सकते हैं:

  1. कैनवस का उपयोग करके एसवीजी छवि प्रदान करने के लिए कैनवस जावास्क्रिप्ट लाइब्रेरी का उपयोग करें : https://github.com/gabelerner/canvg
  2. इन निर्देशों के अनुसार, कैनवस से JPG (या PNG) के रूप में एन्कोड किए गए डेटा URI को कैप्चर करें: HTML कैनवास को gif / jpg / png / pdf के रूप में कैप्चर करें?

28
यह कड़ाई से जावास्क्रिप्ट नहीं है, लेकिन HTML5 भी। यह IE8 या HTML5 कैनवस का समर्थन नहीं करने वाले किसी भी अन्य ब्राउज़र पर काम नहीं करेगा।
जेम्स

16
यदि ब्राउज़र एसवीजी और कैनवस का समर्थन करता है, तो एसवीजी को मेमोरी में लोड करने के लिए एक बहुत सरल तरीका होगा और फिर कैनवग की आवश्यकता के बिना इसे एक कैनवास में पेंट करें, जो एक बहुत बड़ी लाइब्रेरी है क्योंकि यह सभी एसवीजी पार्स को संभालता है। एक SVG- सपोर्ट करने वाला ब्राउज़र पहले से ही मुफ्त में उपलब्ध कराता है। मुझे यकीन नहीं है कि यह मूल उपयोग-मामले को संतुष्ट करता है, लेकिन यदि ऐसा है, तो विवरण के लिए इस संसाधन को देखें
प्रेमसागर

120
IE8 का समर्थन नहीं करने के लिए धन्यवाद। लोगों को समझना चाहिए कि यह आगे बढ़ने का समय है।
साकेत साहू

9
इसे प्राप्त करने के लिए आप जावास्क्रिप्ट SVG लाइब्रेरी पाब्लो का उपयोग कर सकते हैं (मैंने इसे बनाया था)। ऑटो-डाउनलोड की गई छवि के लिए toImage()और भी देखें download()
प्रेमसागर

2
svgopen.org/2010/papers/62-From_SVG_to_Canvas_and_Back - पूरी तरह से काम करता है! [लिंक पेज पर, sourceSVG = $ ("# your_svg_elem_name"))। (0)]
विजय सिंह

44

jbeard4 समाधान ने खूबसूरती से काम किया।

मैं SVG बनाने के लिए राफेल स्केचपैड का उपयोग कर रहा हूँ । चरण 1 में फ़ाइलों के लिए लिंक।

एक सेव बटन के लिए (svg का "एडिटर" है, कैनवस का "कैनवास" है):

$("#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लेकिन jquery html () फ़ंक्शन svg टैग को नहीं जोड़ता है, इसलिए यह कोड मेरे लिए काम करता है लेकिन मुझे canvg को लाइव करने के लिए संपादित करने की आवश्यकता हैcanvg('canvas', '<svg>'+$("#editor").html()+'</svg>');
Luckyn

1
@ ल्यूकिन अगर आप $(selector).html()अपने एसवीजी तत्व के माता-पिता को बुलाते हैं , तो यह काम करेगा
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()
फ्लोरियन लेटेजब

धन्यवाद!! मुझे यह पसंद है कि यह "स्थानीय" एसवीजी एचटीएमएल नोड और दूरस्थ एसवीजी URL दोनों के लिए कैसे काम करता है। इसके अलावा, यह एक पूर्ण बाहरी पुस्तकालय की आवश्यकता नहीं है
Fabricio PH

7

छवि को png करने के लिए SVG को URL और blob URL को एसवीजी में बदलने का उपाय

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

यदि आप एक वेनिला जावास्क्रिप्ट संस्करण चाहते हैं, तो आप बेबेल वेबसाइट पर जा सकते हैं और कोड को वहां ट्रांसपाइल कर सकते हैं।


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 src="data:image/png;base64, [base64 data]"/>

यह ब्राउज़र में काम करता है।


सेवा मृत प्रतीत होती है।

3
हमारा मेजबान फर्जी अनुरोधों के साथ मारा गया था। इसलिए हमने इसे नीचे उतारने का फैसला किया। अब आपको अपना स्वयं का सर्वर चलाना होगा। अधिक जानकारी के लिए github रेपो देखें।
फूक डो

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
@ Xsmael DOMParser इंटरफ़ेस डेवलपर
Mahdi

1

Svgpngशर्तों के आधार पर परिवर्तित किया जा सकता है:

  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/nil Arizona/path2d-polyfill

  1. svgउपयोग करके कैनवास बनाएं और ड्रा करें .drawImage():
    • कैनवास तत्व बनाओ
    • svg xml से svgBlob ऑब्जेक्ट बनाते हैं
    • domUrl.createObjectURL (svgBlob) से एक url ऑब्जेक्ट बनाना;
    • एक छवि वस्तु बनाएँ और छवि src को url असाइन करें
    • कैनवास में छवि बनाएं
    • कैनवास से png डेटा स्ट्रिंग प्राप्त करें: कैनवस .toDataURL ();

अच्छा विवरण: http://ramblings.mcpher.com/Home/excelquirks/gassnips/svgtopng

ध्यान दें कि कैनवास के मंच पर आपको अपवाद मिलेगा ।toDataURL (); ऐसा इसलिए है क्योंकि IE में बहुत अधिक सुरक्षा प्रतिबंध है और कैनवास को वहां की छवि बनाने के बाद आसानी से व्यवहार करता है। अन्य सभी ब्राउज़र केवल तभी प्रतिबंधित होते हैं जब छवि क्रॉस मूल है।

  1. canvgजावास्क्रिप्ट लाइब्रेरी का उपयोग करें । यह अलग पुस्तकालय है लेकिन इसके उपयोगी कार्य हैं।

पसंद:

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

3 लिंक टूट गया है
Serdar Sayın

हाँ सचमुच। मुझे नहीं पता कि अब वहां कैसे पहुंचा जाए। लेकिन उपरोक्त विवरण कुछ समझ के लिए पर्याप्त हो सकता है। भविष्य के सह के लिए अच्छा विचार संदर्भ के बाद कुछ संदर्भ की नकल करता है
एलेक्स वोवचुक

0

मैंने हाल ही में जावास्क्रिप्ट के लिए छवि अनुरेखण पुस्तकालयों की एक जोड़ी की खोज की है जो वास्तव में बिटमैप के लिए एक स्वीकार्य सन्निकटन बनाने में सक्षम हैं, दोनों आकार और गुणवत्ता। मैं यह जावास्क्रिप्ट लाइब्रेरी और सीएलआई विकसित कर रहा हूं:

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

जो उन सभी के लिए एकीकृत एपीआई प्रदान करता है, जो ब्राउज़र और नोड का समर्थन करते हैं, गैर-डोम के आधार पर और एक कमांड लाइन टूल।

लोगो / कार्टून / छवियों को परिवर्तित करने के लिए यह उत्कृष्ट कार्य करता है। तस्वीरों / यथार्थवाद के लिए कुछ ट्विकिंग की आवश्यकता होती है क्योंकि आउटपुट का आकार बहुत बढ़ सकता है।

इसमें एक खेल का मैदान है, हालांकि अभी मैं एक बेहतर काम कर रहा हूं, इसका उपयोग करना आसान है, क्योंकि अधिक सुविधाएँ जोड़ी गई हैं:

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.