0

我确实有可用的 svg 代码作为 javascript 变量中的文本。我需要将其设置为对象标签(不是 SVG 或 IMG)中的图像。这可能吗?

这在使用缓存的 SVG 代码创建 SVG 对象标签中进行了讨论,但没有任何响应。

4

1 回答 1

1

有几种方法可以做到这一点,但它们并不都允许您访问对象的 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>

但是这个小提琴将适用于除 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);
};

作为小提琴。

于 2017-11-12T04:04:44.630 回答