Существуют и другие решения, но AJAX действительно прост, если вы планируете добавить SVG в ваш документ.
Но будьте осторожны, это может быть не очень хорошая идея.
Как вы, вероятно, знаете, SVG являются документами, и их узлы могут иметь атрибуты id
. id
атрибуты должны быть уникальными для каждого документа, поэтому, если вы добавите дважды один и тот же документ SVG, содержащий узлы с id
, у вас будут дубликаты идентификаторов и, возможно, проблемы.
const svg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
<defs>
<rect id="rect1" x="0" y="0" width="50" height="50" fill="red"/>
</defs>
<use xlink:href="#rect1" stroke="green"/>
</svg>`;
function appendSVGDoc(markup, parent) {
const doc = (new DOMParser).parseFromString(markup, 'image/svg+xml');
const docEl = document.adoptNode(doc.documentElement); parent.appendChild(docEl);
}
// append a first version
appendSVGDoc(svg, document.body);
onclick = e => {
// let's do some modifs
document.getElementById('rect1').setAttribute('fill', 'yellow');
onclick = e => {
// append an other one
appendSVGDoc(svg, document.body);
// guess what color is the rect here?
};
};
<p>click to modify the svg element.</p>
<p>click again to add a new copy of the original svg</p>
Другой пример? Если ваш документ SVG содержит таблицу стилей, то правила этой таблицы стилей будут влиять на весь ваш документ:
const svg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="500" height="200">
<style>
:root {
font: 40px Serif;
}
rect {
fill: green;
}
</style>
<text y="50">I'm a big text in an svg image.</text>
<rect x="25" y="75" width="50" height="50"/>
</svg>`;
function appendSVGDoc(markup, parent) {
const doc = (new DOMParser).parseFromString(markup, 'image/svg+xml');
const docEl = document.adoptNode(doc.documentElement); parent.appendChild(docEl);
}
onclick = e => {
appendSVGDoc(svg, document.body);
};
<p>I am a simple html text content, and here is a simple svg <rect> that should be red: <svg width="50" height="50"><rect x="0" y="0" height="50" width="50" fill="red"/></svg></p>
<p> click to append the external SVG </p>
Поэтому, чтобы избежать таких случаев, я могу только посоветовать вам реально загрузить ваши svg docs в
function appendSVGDoc(blob, parent) {
return new Promise((res, rej) => {
const url = URL.createObjectURL(blob);
const iframe = document.createElement('iframe');
iframe.classList.add('svg-viewer');
iframe.onload = e => {
const doc = iframe.contentDocument;
const docEl = doc.documentElement;
// iframe doesn't auto size like <object> would
iframe.width = docEl.getAttribute('width') || '100%';
iframe.height = docEl.getAttribute('height') || '100%';
res(doc);
};
iframe.onerror = rej;
iframe.src = url;
parent.appendChild(iframe);
});
}
fetch(url)
.then(resp => resp.blob())
.then(blob => appendSVGDoc(blob, document.body));
.then(svgdoc => {
// here manipulate the svg document
})
.catch(console.error);
StackSnippets®, чрезмерно защищенный (с нулевым происхождением), который блокирует нам доступ к внутреннему контенту iframes, мне пришлось перевести этот последний пример в jsfiddle .