web-dev-qa-db-ja.com

D3.js(IE、safari、およびchrome)でSVGを作成した後、SVGファイルを保存/エクスポートするにはどうすればよいですか?

現在、D3を使用するWebサイトがあり、ユーザーにSVGをSVGファイルとして保存するオプションを提供したいと思います。私はこれを行うためにcrowbar.jsを使用していますが、クロムでのみ機能します。サファリは何も起こらず、IEはファイルをダウンロードするためにcrowbar.jsで使用されるclick()メソッドで拒否されたアクセスを与えます。

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

サファリ、IEおよびchrome?)のWebサイトのSVG要素に基づいてSVGファイルをダウンロードするにはどうすればよいですか?

51
Vanquiza

5つのステップがあります。私はよくこの方法を使用してインラインsvgを出力します。

  1. 出力するインラインsvg要素を取得します。
  2. xMLSerializerでsvgソースを取得します。
  3. svgおよびxlinkの名前空間を追加します。
  4. encodeURIComponentメソッドによってsvgのURLデータスキームを構築します。
  5. このURLを「a」要素のhref属性に設定し、このリンクを右クリックして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.
51
defghi1977

これはすでに回答済みであり、その回答はほとんどの場合うまく機能します。ただし、svgイメージが大きい(約1MB)場合、Chrome(Firefoxではありません)で失敗することがわかりました。Blobherehere のように構築します。唯一の違いはtype引数です。私のコードでは、ボタンを1回押すだけでユーザーのsvgをダウンロードできます。で:

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);
40

Daveとdefghi1977の回答を組み合わせます。再利用可能な関数は次のとおりです。

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

呼び出し例:

saveSvg(svg, 'test.svg')
17
senz

ここですべての解決策を試しましたが、何もうまくいきませんでした。私の写真は常にd3.jsキャンバスよりも小さくなりました。

キャンバスwidthheightを設定し、clearRectcontextを実行して機能させる必要がありました。これが私の作業バージョンです

エクスポート関数:

var svgHtml = document.getElementById("d3-canvas"),
    svgData = new XMLSerializer().serializeToString(svgHtml),
    svgBlob = new Blob([svgData], {type:"image/svg+xml;charset=utf-8"}),
    bounding = svgHtml.getBoundingClientRect(),
    width = bounding.width * 2,
    height = bounding.height * 2,
    canvas = document.createElement("canvas"),
    context = canvas.getContext("2d"),
    exportFileName = 'd3-graph-image.png';

//Set the canvas width and height before loading the new Image
canvas.width = width;
canvas.height = height;

var image = new Image();
image.onload = function() {
    //Clear the context
    context.clearRect(0, 0, width, height);
    context.drawImage(image, 0, 0, width, height);

    //Create blob and save if with FileSaver.js
    canvas.toBlob(function(blob) {
        saveAs(blob, exportFileName);
    });     
};
var svgUrl = URL.createObjectURL(svgBlob);
image.src = svgUrl;

FileSaver.js を使用してファイルを保存します。

これは私のキャンバス作成です、ここで名前空間の問題を解決することに注意してください

d3.jsキャンバスの作成:

var canvas = d3.select("body")
    .insert("svg")
    .attr('id', 'd3-canvas')
    //Solve the namespace issue (xmlns and xlink)
    .attr("xmlns", "http://www.w3.org/2000/svg")
    .attr("xmlns:xlink", "http://www.w3.org/1999/xlink")
    .attr("width", width)
    .attr("height", height);
0
Ludovic Feltz

このスニペットを機能させるには、FileSaver.jsが必要です。

function save_as_svg(){


        var svg_data = document.getElementById("svg").innerHTML //put id of your svg element here

        var head = '<svg title="graph" version="1.1" xmlns="http://www.w3.org/2000/svg">'

        //if you have some additional styling like graph edges put them inside <style> tag

        var style = '<style>circle {cursor: pointer;stroke-width: 1.5px;}text {font: 10px arial;}path {stroke: DimGrey;stroke-width: 1.5px;}</style>'

        var full_svg = head +  style + svg_data + "</svg>"
        var blob = new Blob([full_svg], {type: "image/svg+xml"});  
        saveAs(blob, "graph.svg");


};
0

補足として、RGBインラインカラーを使用しないでください。 #FFF000

はxmlでは無効であり、htmlエンティティにエンコードする必要があるようです。

代わりにhslまたはhslaを使用するのが最適です!

0
NVRM