How to Check If an Embedded Svg Document Is Loaded in an HTML Page

How to know when an embed element's content has loaded

As @RGraham points out in a comment, the <embed> element raises the load event when its content is ready.

So my code becomes:

var e = document.createElement('embed');
e.src = "img/z-slider.svg";
e.type = "image/svg+xml";
document.body.appendChild(e);

e.addEventListener('load', function()
{
// Operate upon the SVG DOM here
e.getSVGDocument().querySelector('#some-node').textContent = "New text!";
});

This is better than polling as there is no flicker. The SVG is modified immediately upon load, before it is painted.

Waiting for element load after page has loaded

Relevant: How to check if an embedded SVG document is loaded in an html page?

If you have control over the SVG document, could you not add a script in it that calls a function in the browser window?

Or, as the answer to that question suggested, polling to see if the SVG document has finished loading.

Do I use img, object, or embed for SVG files?

I can recommend the SVG Primer (published by the W3C), which covers this topic: http://www.w3.org/Graphics/SVG/IG/resources/svgprimer.html#SVG_in_HTML

If you use <object> then you get raster fallback for free*:

<object data="your.svg" type="image/svg+xml">
<img src="yourfallback.jpg" />
</object>

*) Well, not quite for free, because some browsers download both resources, see Larry's suggestion below for how to get around that.

2014 update:

  • If you want a non-interactive svg, use <img> with script fallbacks
    to png version (for older IE and android < 3). One clean and simple
    way to do that:

    <img src="your.svg" onerror="this.src='your.png'">.

    This will behave much like a GIF image, and if your browser supports declarative animations (SMIL) then those will play.

  • If you want an interactive svg, use either <iframe> or <object>.

  • If you need to provide older browsers the ability to use an svg plugin, then use <embed>.

  • For svg in css background-image and similar properties, modernizr is one choice for switching to fallback images, another is depending on multiple backgrounds to do it automatically:

    div {
    background-image: url(fallback.png);
    background-image: url(your.svg), none;
    }

    Note: the multiple backgrounds strategy doesn't work on Android 2.3 because it supports multiple backgrounds but not svg.

An additional good read is this blogpost on svg fallbacks.

How to access SVG elements with Javascript

Is it possible to do it this way, as opposed to using something like Raphael or jQuery SVG?

Definitely.

If it is possible, what's the technique?

This annotated code snippet works:

<!DOCTYPE html>
<html>
<head>
<title>SVG Illustrator Test</title>
</head>
<body>

<object data="alpha.svg" type="image/svg+xml"
id="alphasvg" width="100%" height="100%"></object>

<script>
var a = document.getElementById("alphasvg");

// It's important to add an load event listener to the object,
// as it will load the svg doc asynchronously
a.addEventListener("load",function(){

// get the inner DOM of alpha.svg
var svgDoc = a.contentDocument;
// get the inner element by id
var delta = svgDoc.getElementById("delta");
// add behaviour
delta.addEventListener("mousedown",function(){
alert('hello world!')
}, false);
}, false);
</script>
</body>
</html>

Note that a limitation of this technique is that it is restricted by the same-origin policy, so alpha.svg must be hosted on the same domain as the .html file, otherwise the inner DOM of the object will be inaccessible.

Important thing to run this HTML, you need host HTML file to web server like IIS, Tomcat

Nonstandard view of an external SVG document embedded in HTML via a fragment identifier or view specification: How to manipulate the viewBox?

When you use a non default view (either <view> or #svgView()), its parameters will be used instead of the ones of the root element.

So if you set a viewBox parameter through this view, the root element's viewBox will get discarded, and editing it won't change anything.

There used to be an SVGSVGElement.currentView property being defined in SVG1.1, but it got dropped in SVG2 and among popular modern browsers, only Safari did implement it.

Since there is no clean API to deal with it, you will need to do something a bit dirty by checking the location.hash if it's pointing to such a view and edit it or the element it points to.

However if I understand your case correctly, you have full control over the svg and you know for sure you'll be using such a view, so the easiest is probably to use a <view> element and then to edit its viewBox attribute, except that Chrome is buggy and doesn't update the view when this happens...

Here is a live snippet where the edition is made from inside the svg document itself since StackSnippets iframes don't allow accessing the inner doc which only works in Firefox.

const svg_content = `
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" >
<view id="my_view" viewBox="0 0 400 400" />
<rect fill="red" x="0" y="0" width="20" height="20"/>
<script>
onmousemove = (evt) => {
const view = document.getElementById("my_view");
const viewBox = view.viewBox.baseVal;
viewBox.x = evt.clientX * -1;
viewBox.y = evt.clientY * -1;
};
<\/script>
</svg>`;
const blob = new Blob([svg_content], { type: "image/svg+xml" });
const url = URL.createObjectURL(blob);
const object = document.getElementById("obj");
object.data = url + "#my_view";
object {
border: 1px solid;
}
<object id="obj"></object>


Related Topics



Leave a reply



Submit