假设这样的元素链接到外部SVG图像:
<div style="background-image: url("/images/tags/icon/star.svg");"></div>
如果该图像已经作为背景图像渲染,那么将此SVG图像转换为嵌入式SVG(文档中的其他位置)有哪些选择?
是this answer中建议的唯一重新加载外部文件的选项吗?
目标是在可能的情况下再次跳过加载SVG文件。
答案 0 :(得分:1)
还有其他解决方案,但是如果您打算在文档中附加SVG,则AJAX确实是最简单的。
但是请注意,这可能不是一个好主意。
您可能知道,SVG是文档,它们的节点可以具有id
属性。 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文档加载到
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®受过度保护(起源于空)自身阻止了我们访问内部iframe内容,我不得不将最后一个示例外包给jsfiddle。