【问题标题】:How to select an SVG element inside an <object> tag with JavaScript?如何使用 JavaScript 在 <object> 标记内选择 SVG 元素?
【发布时间】: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,它会禁止某些事情。

标签: javascript html angularjs svg cross-domain


【解决方案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')之类的吗?

    【讨论】:

      猜你喜欢
      • 2020-04-11
      • 2020-04-05
      • 2021-02-03
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      • 1970-01-01
      • 2018-06-15
      相关资源
      最近更新 更多