Как сохранить/экспортировать SVG файл после создания SVG с помощью D3.js(IE, сафари и хром)?
В настоящее время у меня есть сайт, использующий D3, и я хотел бы, чтобы у пользователя была возможность сохранить SVG в качестве SVG файла. Я использую crowbar.js для этого, но он работает только на хроме. Ничего не происходит из сафари, и IE дает доступ, запрещенный методом click()
, используемым в файле crowbar.js, для загрузки файла.
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);
Как загрузить SVG файл на основе элемента SVG на моем веб-сайте в сафари, IE и хром?
Ответы
Ответ 1
Есть 5 шагов. Я часто использую этот метод для вывода встроенного svg.
- Получить встроенный элемент svg для вывода.
- получить источник svg с помощью XMLSerializer.
- добавить пространства имен svg и xlink.
- построить схему данных url для svg методом encodeURIComponent.
- установите этот url в атрибут href какого-либо элемента "a" и щелкните правой кнопкой эту ссылку, чтобы загрузить файл 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 href attribute.
document.getElementById("link").href = url;
//you can download svg file by right click menu.
Ответ 2
Я знаю, что на этот вопрос уже дан ответ, и этот ответ хорошо работает большую часть времени. Однако я обнаружил, что это не удалось в Chrome (но не в Firefox), если изображение svg было большого размера (около 1 МБ). Это работает, если вы вернетесь к использованию конструкции Blob
, как описано здесь и здесь. Единственная разница - аргумент типа. В моем коде я хотел одним нажатием кнопки загрузить 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);
Октябрь 2019 г., редактирование:
Комментарии показали, что этот код будет работать даже без добавления downloadLink
к document.body
и последующего удаления его после click()
. Я считаю, что раньше работал на Firefox, но на данный момент он больше не работает (Firefox требует, чтобы вы добавили, а затем удалили downloadLink
). Код работает на Chrome в любом случае.
Ответ 3
Сочетание ответов Дэйва и Дегги1977. Вот многократно используемая функция:
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')
Ответ 4
Чтобы этот фрагмент работал, вам нужен 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");
};
Ответ 5
Я пробовал каждое решение здесь, и у меня ничего не получалось. Моя картинка всегда была меньше, чем у меня на холсте d3.js.
Мне пришлось установить холст width
, height
, а затем сделать clearRect
на context
, чтобы он заработал. Вот моя рабочая версия
Функция экспорта:
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);
Ответ 6
С другой стороны, не используйте встроенные цвета RGB. # FFF000
Похоже, что # недопустим в xml, его нужно закодировать в html-сущность.
Лучше всего использовать вместо этого hsl или hsla!