最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

html - How to select an SVG element inside an <object> tag with JavaScript? - Stack Overflow

programmeradmin0浏览0评论

In my Angular appliation, I want to be able to select the embedded SVG element of an <object> tag using JavaScript or Angular jqLite.

Normally, to do this operation, one must write something similar to:

// 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);

In my console, objElement returns the plete <object> with the <svg> element and its contents (assume that data attribute contains the full base64 data string (b64)).

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

However, getSVGDocument() returns null and contentDocument returns

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

Why can't I retrieve the SVG element? How can I get the SVG element correctly? I've already looked into many articles and I just can't get the <svg> element. Could this have something to do with cross-origin policy?

In my Angular appliation, I want to be able to select the embedded SVG element of an <object> tag using JavaScript or Angular jqLite.

Normally, to do this operation, one must write something similar to:

// 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);

In my console, objElement returns the plete <object> with the <svg> element and its contents (assume that data attribute contains the full base64 data string (b64)).

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

However, getSVGDocument() returns null and contentDocument returns

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

Why can't I retrieve the SVG element? How can I get the SVG element correctly? I've already looked into many articles and I just can't get the <svg> element. Could this have something to do with cross-origin policy?

Share Improve this question asked Oct 27, 2015 at 19:03 DramosDramos 811 silver badge2 bronze badges 6
  • You need to wait for the onload event of the object to fire before accessing its contents. – Robert Longson Commented Oct 27, 2015 at 19:11
  • If I enclose the getSVGDocument() inside a onload event, I get 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. – Dramos Commented Oct 27, 2015 at 19:18
  • Is this Chrome? I imagine you're blocked by its security model. You might try a different UA – Robert Longson Commented Oct 27, 2015 at 19:22
  • Yes, I'm developing on Chrome. Do you mean User Agent? How can I toggle its security model? – Dramos Commented Oct 27, 2015 at 19:33
  • Robert means try a different browser, like Firefox. Chrome has a more restrictive security model. For instance it disallows some things if you are using file:// URLs. – Paul LeBeau Commented Oct 28, 2015 at 0:57
 |  Show 1 more ment

3 Answers 3

Reset to default 5

I was also unable to select the SVG using things like document.querySelector("svg") even though the SVG was clearly loaded in the DOM. Turned out I needed to do this:

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

Apparently there's a boundary between the main document and this sub-document, and you have to bridge the divide using contentDocument.

It seems getSVGDocument() is deprecated. Have you tried something like document.querySelector('object svg') ?

The reason you can't see the object is because you are most likely probing for it before DOM load. Try:

// 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');
    }
  }
}
发布评论

评论列表(0)

  1. 暂无评论