2014-04-22 21 views
29

Mam obecnie stronę internetową za pomocą D3 i chciałbym, aby użytkownik miał możliwość zapisania SVG jako pliku SVG. Używam crowbar.js do tego, ale działa tylko na chrome. Nic nie dzieje się w Safari, a IE daje odmowę dostępu na metodę click() używaną w crowbar.js do pobrania pliku.Jak zapisać/wyeksportować plik SVG po utworzeniu SVG w D3.js (IE, safari i chrome)?

var e = document.createElement('script'); 

if (window.location.protocol === 'https:') { 
    e.setAttribute('src', 'https://raw.github.com/NYTimes/svg-crowbar/gh-pages/svg-crowbar.js'); 
} else { 
    e.setAttribute('src', 'http://nytimes.github.com/svg-crowbar/svg-crowbar.js'); 
} 

e.setAttribute('class', 'svg-crowbar'); 
document.body.appendChild(e); 

Jak pobrać plik SVG oparte na elemencie SVG na mojej stronie internetowej w Safari, IE i Chrome?

Odpowiedz

37

Jest 5 kroków. Często używam tej metody do wyprowadzania svg inline.

  1. pobierz element svg na wyjście.
  2. pobierz źródło svg przez XMLSerializer.
  3. dodaj spacje nazw svg i xlink.
  4. Skonstruuj schemat danych URL svg metodą encodeURIComponent.
  5. Ustaw ten URL na atrybut href jakiegoś elementu "a", a następnie kliknij ten link prawym przyciskiem myszy, aby pobrać plik SVG.

//get svg element. 
var svg = document.getElementById("svg"); 

//get svg source. 
var serializer = new XMLSerializer(); 
var source = serializer.serializeToString(svg); 

//add name spaces. 
if(!source.match(/^<svg[^>]+xmlns="http\:\/\/www\.w3\.org\/2000\/svg"/)){ 
    source = source.replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg"'); 
} 
if(!source.match(/^<svg[^>]+"http\:\/\/www\.w3\.org\/1999\/xlink"/)){ 
    source = source.replace(/^<svg/, '<svg xmlns:xlink="http://www.w3.org/1999/xlink"'); 
} 

//add xml declaration 
source = '<?xml version="1.0" standalone="no"?>\r\n' + source; 

//convert svg source to URI data scheme. 
var url = "data:image/svg+xml;charset=utf-8,"+encodeURIComponent(source); 

//set url value to a element's href attribute. 
document.getElementById("link").href = url; 
//you can download svg file by right click menu. 
+0

Dziękuję za odpowiedź! To pobiera svg dla mnie, chociaż wszystko idzie na czarno, a kolorystyka jest bardzo dziwna. Dlaczego to? Możesz zobaczyć, co mam na myśli na mojej stronie, zastosowałem twój sugerowany kod: http://servers.binf.ku.dk/hemaexplorerbeta/ - Po prostu kliknij "wyślij", a następnie "wyeksportuj wykres". Dziękuję bardzo – Vanquiza

+1

Ten przykład jest prosty. Jeśli używasz stylu css przez zewnętrzne pliki css według elementu linku, link svg i arkusz stylów został uszkodzony. Tak więc ten problem zostanie rozwiązany przez dołączenie danych stylu do wbudowanego svg. – defghi1977

+0

"Ten problem zostanie rozwiązany przez dołączenie danych stylu do wbudowanego svg." Czy możesz mi to wytłumaczyć w inny sposób? Nie do końca rozumiem. – Vanquiza

21

wiem, że to już odpowiedział, a odpowiedź działa dobrze przez większość czasu. Zauważyłem jednak, że nie udało się to w Chrome (ale nie Firefoksie), jeśli obraz svg był duży (około 1 MB). Działa, jeśli wrócisz do korzystania z konstruktu Blob, zgodnie z opisem here i here. Jedyną różnicą jest argument typu. W moim kodu chciałem jednego naciśnięcia przycisku, aby pobrać SVG dla użytkownika, co osiągnąłem z:

var svgData = $("#figureSvg")[0].outerHTML; 
var svgBlob = new Blob([svgData], {type:"image/svg+xml;charset=utf-8"}); 
var svgUrl = URL.createObjectURL(svgBlob); 
var downloadLink = document.createElement("a"); 
downloadLink.href = svgUrl; 
downloadLink.download = "newesttree.svg"; 
document.body.appendChild(downloadLink); 
downloadLink.click(); 
document.body.removeChild(downloadLink); 
+1

To zadziałało naprawdę dobrze w Chrome! Dałbym +100 za tę prostą odpowiedź! – kashiraja

+0

Wygląda na to, że działa bez dodawania i usuwania 'downloadLink' w' document.body' –

+0

'.HTMLHTML' nie działa w przeglądarce Internet Explorer. Ale możesz użyć 'XMLSerializer()' jako [defghi1977] (https://stackoverflow.com/a/23218877/3620572). Wszystko inne zachowuje się tak samo. – roland

0

Łącząc Dave i defghi1977 odpowiedzi. Tutaj jest funkcja wielokrotnego użytku:

function saveSvg(svgEl, name) { 
    svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg"); 
    var svgData = svgEl.outerHTML; 
    var preface = '<?xml version="1.0" standalone="no"?>\r\n'; 
    var svgBlob = new Blob([preface, svgData], {type:"image/svg+xml;charset=utf-8"}); 
    var svgUrl = URL.createObjectURL(svgBlob); 
    var downloadLink = document.createElement("a"); 
    downloadLink.href = svgUrl; 
    downloadLink.download = name; 
    document.body.appendChild(downloadLink); 
    downloadLink.click(); 
    document.body.removeChild(downloadLink); 
} 

Inwokacja przykład:

saveSvg(svg, 'test.svg') 
Powiązane problemy