KevBot KevBot - 1 month ago 8
Javascript Question

Can I get the contents of a use element that is referencing an external svg?

I am building a web component that renders svg icons onto the page in Shadow Dom. i.e.

<ba-icon i="airplane"></ba-icon>


I have an external svg sprite file, that essentially has a ton of SVG icons in it.

The internals of the web component essentially render the following into Shadow Dom:

<svg>
<use xlink:href="i.dist.svg#i-airplane"></use>
<svg>


Everything is correctly rendering on the screen, but I am after some information that is embedded inside of the SVG, specifically the information contained in the
viewbox
, (for example:
viewBox="0 0 32 32"
).

I know that what is rendered in the
use
is input into the Shadow Dom as well. But I am trying to find another way of obtaining the information embedded into the
use
. I tried to ajax the contents of the svg, but this is turning into a big problem for multiple icons on the page since each instance of the web component is now making that call. How else could I do this?

For reference:

enter image description here

Answer

Actually there are manys ways to acheive this, depending of the structure of the SVG file you use, and what you want to do.

With SVG sprites as an external file, you can take profit of the HTML Imports technology to parse the file:

<head>
...
  <link id="ic" rel="import" href="i.dist.svg">

  <script>
    document.registerElement( "ba-icon", { 
        prototype:  Object.create( HTMLElement.prototype, {
            createdCallback: {
                value: function () 
                {
                    var name = "i-" + this.getAttribute( 'i' )
                    var sh = this.createShadowRoot()
                    sh.innerHTML = '<svg><use xlink:href="i.dist.svg#' + name + '"/>'
                    this.setAttribute( "i-viewBox", ic.import.querySelector( 'svg#' + name ).getAttribute( "viewBox" ) )
                }
            }
        } )
    } )
  </script>
</head>

The SVG file is not imported twice because it is cached by the browser.

Note: This solution (using <use>) may not be the fastest but it is the simplest to code, and to understand. It depends on what you really want to do with the attributes (and when).

Comments