使用 javascript 使用 SVG 代码填充对象标签
Populate object tag with SVG code with javascript
我在 javascript 的变量中确实有可用的 svg 代码作为文本。我需要将它设置为对象标签中的图像(不是 SVG 或 IMG)。这可能吗?
Create SVG Object tag with Cached SVG code 对此进行了讨论,但没有任何回应。
有几种方法可以做到这一点,但并不是所有方法都允许您访问对象的 contentDocument...
最简单的方法是将 SVG 标记转换为数据 URI。
但是浏览器会认为这个文档是跨源资源,然后会禁止你通过js访问它。
// an svg string
const svgStr = `<svg width="120" height="120" viewBox="0 0 120 120"
xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="100" height="100"/>
</svg>`;
// as dataURI
const dataURI = 'data:image/svg+xml;charset=utf8, '+ encodeURIComponent(svgStr);
obj.data = dataURI;
// do some checks after it has loaded
obj.onload = e => {
console.log('loaded');
try{
console.log(obj.contentDocument.documentElement.nodeName);
}
catch(err){
console.log('but cant access the document...');
console.error(err);
}
};
<object id="obj"></object>
在大多数浏览器中避免这种情况的一种方法是使用 blobURI,应该 标记文档的来源,从而允许我们访问文档。
但是 IE 并没有在 blobURIs 上设置这个来源...所以这个浏览器也不允许你访问 contentDocument。
以下代码段将在所有浏览器中充当 IE,因为 StackSnippets iframe 是 null 来源的:
// an svg string
const svgStr = `<svg width="120" height="120" viewBox="0 0 120 120"
xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="100" height="100"/>
</svg>`;
// as blobURI
const blob = new Blob([svgStr], {type:'image/svg+xml'})
const blobURI = URL.createObjectURL(blob);
obj.data = blobURI;
// do some checks after it has loaded
obj.onload = e => {
console.log('loaded');
try{
console.log(obj.contentDocument.documentElement.nodeName);
}
catch(err){
console.log('but cant access the document...');
console.error(err);
}
};
<object id="obj"></object>
但是 this fiddle 可以在除 IE 浏览器之外的所有浏览器中使用。
因此,一种也适用于 IE 的方法是使用一个空的 HTML 文档,从同一来源提供,我们将在加载后附加 svg。
// first load an same-origin document (not sure if about:blank works in IE...)
obj.data = 'empty.html';
// once it has loaded
obj.onload = e => {
// parse our svgString to a DOM element
const svgDoc = new DOMParser().parseFromString(svgStr, 'image/svg+xml');
const objDoc = obj.contentDocument;
// ask the object's document to adopt the svg node
const toAppend = objDoc.adoptNode(svgDoc.documentElement);
// now we can append it and it will display
objDoc.documentElement.appendChild(toAppend);
};
我在 javascript 的变量中确实有可用的 svg 代码作为文本。我需要将它设置为对象标签中的图像(不是 SVG 或 IMG)。这可能吗?
Create SVG Object tag with Cached SVG code 对此进行了讨论,但没有任何回应。
有几种方法可以做到这一点,但并不是所有方法都允许您访问对象的 contentDocument...
最简单的方法是将 SVG 标记转换为数据 URI。
但是浏览器会认为这个文档是跨源资源,然后会禁止你通过js访问它。
// an svg string
const svgStr = `<svg width="120" height="120" viewBox="0 0 120 120"
xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="100" height="100"/>
</svg>`;
// as dataURI
const dataURI = 'data:image/svg+xml;charset=utf8, '+ encodeURIComponent(svgStr);
obj.data = dataURI;
// do some checks after it has loaded
obj.onload = e => {
console.log('loaded');
try{
console.log(obj.contentDocument.documentElement.nodeName);
}
catch(err){
console.log('but cant access the document...');
console.error(err);
}
};
<object id="obj"></object>
在大多数浏览器中避免这种情况的一种方法是使用 blobURI,应该 标记文档的来源,从而允许我们访问文档。 但是 IE 并没有在 blobURIs 上设置这个来源...所以这个浏览器也不允许你访问 contentDocument。
以下代码段将在所有浏览器中充当 IE,因为 StackSnippets iframe 是 null 来源的:
// an svg string
const svgStr = `<svg width="120" height="120" viewBox="0 0 120 120"
xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="100" height="100"/>
</svg>`;
// as blobURI
const blob = new Blob([svgStr], {type:'image/svg+xml'})
const blobURI = URL.createObjectURL(blob);
obj.data = blobURI;
// do some checks after it has loaded
obj.onload = e => {
console.log('loaded');
try{
console.log(obj.contentDocument.documentElement.nodeName);
}
catch(err){
console.log('but cant access the document...');
console.error(err);
}
};
<object id="obj"></object>
但是 this fiddle 可以在除 IE 浏览器之外的所有浏览器中使用。
因此,一种也适用于 IE 的方法是使用一个空的 HTML 文档,从同一来源提供,我们将在加载后附加 svg。
// first load an same-origin document (not sure if about:blank works in IE...)
obj.data = 'empty.html';
// once it has loaded
obj.onload = e => {
// parse our svgString to a DOM element
const svgDoc = new DOMParser().parseFromString(svgStr, 'image/svg+xml');
const objDoc = obj.contentDocument;
// ask the object's document to adopt the svg node
const toAppend = objDoc.adoptNode(svgDoc.documentElement);
// now we can append it and it will display
objDoc.documentElement.appendChild(toAppend);
};