如何使用 JavaScript 在 <object> 标记内选择 SVG 元素?

Posted

技术标签:

【中文标题】如何使用 JavaScript 在 <object> 标记内选择 SVG 元素?【英文标题】:How to select an SVG element inside an <object> tag with JavaScript? 【发布时间】:2016-01-27 08:45:13 【问题描述】:

在我的 Angular 应用程序中,我希望能够使用 javascript 或 Angular jqLit​​e 选择 &lt;object&gt; 标记的嵌入 SVG 元素。

通常,要执行此操作,必须编写类似以下内容:

// Create <object> element of the SVG
var objElement = document.createElement('object');
objElement.setAttribute('type',"image/svg+xml");

// Assume $rootScope.b64 contains the base64 data of the SVG
objElement.setAttribute('data', $rootScope.b64);

// Append the <object> inside the DOM's body
angular.element(document.body).append(objElement);

console.log(objElement);
console.log(objElement.getSVGDocument());
console.log(objElement.contentDocument);

在我的控制台中,objElement 返回带有 &lt;svg&gt; 元素及其内容的完整 &lt;object&gt;(假设 data 属性包含完整的 base64 数据字符串 (b64))。

    <object id="svgObject" data="b64" type="image/svg+xml">
          #document
             <svg>
             </svg>
    </object>

但是,getSVGDocument() 返回 nullcontentDocument 返回

    #document
       <html>
          <head></head>
          <body></body>
       <html>

为什么我无法检索 SVG 元素?如何正确获取 SVG 元素?我已经查看了很多文章,但我无法获得 &lt;svg&gt; 元素。这可能与跨域政策有关吗?

【问题讨论】:

在访问其内容之前,您需要等待对象的 onload 事件触发。 如果我将 getSVGDocument() 包含在 onload 事件中,我会得到 Uncaught SecurityError: Failed to execute 'getSVGDocument' on 'HTMLObjectElement': Blocked a frame with origin "http://127.0.0.1:8080" from accessing a frame with origin "null". The frame requesting access has a protocol of "http", the frame being accessed has a protocol of "data". Protocols must match. 这是 Chrome 吗?我想你被它的安全模型阻止了。您可以尝试不同的 UA 是的,我正在 Chrome 上开发。你的意思是用户代理?如何切换其安全模型? Robert 的意思是尝试不同的浏览器,比如 Firefox。 Chrome 具有更严格的安全模型。例如,如果您使用file:// URL,它会禁止某些事情。 【参考方案1】:

您看不到该对象的原因是您很可能在 DOM 加载之前对其进行探测。试试:

// Create <object> element of the SVG
var objElement = document.createElement('object');
objElement.setAttribute('type',"image/svg+xml");

// Assume $rootScope.b64 contains the base64 data of the SVG
objElement.setAttribute('data', $rootScope.b64);

// Append the <object> inside the DOM's body
angular.element(document.body).append(objElement);

objElement.addEventListener('load', doStuff);

function doStuff() 
  console.log(objElement);
  var svgDoc = getSVGDoc(objElement);
  console.log('svgDoc', svgDoc);



function getSVGDoc(element) 
  console.log('getting obj');
  try 
    return element.contentDocument;
   catch (e) 
    try 
      return element.getSVGDocument();
     catch (e) 
      console.log('SVG unsupported within this browser');
    
  

【讨论】:

【参考方案2】:

即使 SVG 已明确加载到 DOM 中,我也无法使用 document.querySelector("svg") 之类的东西选择 SVG。原来我需要这样做:

var obj = document.querySelector("object");
var svg = obj.contentDocument.querySelector("svg");

显然主文档和该子文档之间存在界限,您必须使用contentDocument 来弥合分歧。

【讨论】:

这对我不起作用。我很容易获得object,但随后.contentDocument 返回null,即使我可以在Chrome devtools Elements 和Console 窗口的对象下清楚地看到#document【参考方案3】:

似乎 getSVGDocument() 已被弃用。你试过document.querySelector('object svg')之类的吗?

【讨论】:

以上是关于如何使用 JavaScript 在 <object> 标记内选择 SVG 元素?的主要内容,如果未能解决你的问题,请参考以下文章

在javascript中如何判断一个变量为空或者undefine

如何在 iPad 上使用 JavaScript/Obj-C 将图像保存到照片库?

如何用Babylon.js导入一个.obj模型

JavaScript的对象

如何在 Javascript 中使用异步等待函数对象?

javascript js - 在循环es6中构建obj <3