如何检查嵌入的 SVG 文档是否已加载到 html 页面中?

IT技术 javascript jquery dom svg
2021-01-14 02:45:48

我需要编辑(使用 javascript)嵌入在 html 页面中的 SVG 文档。

加载 SVG 后,我可以访问 SVG 及其元素的 dom。但是我无法知道 SVG dom 是否已准备好,因此我无法在加载 html 页面时对 SVG 执行默认操作。

要访问 SVG dom,我使用以下代码:

var svg = document.getElementById("chart").getSVGDocument();

其中“chart”是嵌入元素的 id。

如果我在 html 文档准备好后尝试访问 SVG,请通过以下方式:

jQuery(document).ready( function() {
var svg = document.getElementById("chart").getSVGDocument();
...

svg 始终为空。我只需要知道它什么时候不为空,这样我就可以开始操作它了。你知道有没有办法做到这一点?

6个回答

在主文档中的嵌入元素(例如 'embed'、'object'、'iframe')上添加一个onload调用您的函数属性,或在脚本中添加事件侦听器,例如embeddingElm.addEventListener('load', callbackFunction, false). 另一种选择可能是侦听DOMContentLoaded,这取决于您想要它做什么。

您还可以在主文档上添加加载侦听器。jQuery(document).ready并不意味着所有资源都已加载,只是文档本身有一个可以执行操作的 DOM。但是请注意,如果您在整个文档上侦听加载,则在加载该文档中的所有资源、css、javascript 等之前,不会调用回调函数。

如果您使用内联 svg,则jQuery(document).ready可以正常工作。

另请注意,您可能需要考虑使用embeddingElm.contentDocument(如果可用)而不是embeddingElm.getSVGDocument().

如果更改了分配给 DIV 之类的内容的 SVG 文档,从而导致加载该文档,那么 onload 会起作用吗?整个“我们什么时候知道 DOM 和内容真正被加载,以便人们可以调用 SVG 中定义的 ECMAscript 功能或查询 DOM 似乎仍然是 2018 年命中/未命中的命题,根据我所听到的从一些人那里。
2021-03-20 02:45:48
您是否还知道如何在 Angular 测试中在 SVG 对象上触发此加载事件侦听器?
2021-03-21 02:45:48
@jBoive :关于“如果在脚本运行时已经加载了 embeddingElm,则 embeddingElm.addEventListener('load', callbackFunction, false) 将不起作用。 ”:那么类似于stackoverflow.com/a/39993735/923560的解决方案将起作用.
2021-04-06 02:45:48
如果在脚本运行时已经加载了 embeddingElm,embeddingElm.addEventListener('load', callbackFunction, false) 将不起作用。如果您在 SVG 中链接图像(如背景图像),则 DOMContentLoaded 将不起作用。您(不应该)想做:类似于:window.onload 的事情,因为那样您就必须等到所有外部资源也都下载完毕(例如跟踪脚本和广告)
2021-04-12 02:45:48
在 Safari 上,如果 SVG 内容已经加载,load则永远不会触发。
2021-04-12 02:45:48

您可以使用onload事件进行检查。

假设 some.svg 嵌入在 object 标签中:

<body>    
<object id="svgholder" data="some.svg" type="image/svg+xml"></object>
</body>

查询

var svgholder = $('body').find("object#svgholder");

svgholder.load("image/svg+xml", function() {
    alert("some svg loaded");
});

javascript

var svgholder = document.getElementById("svgholder");

svgholder.onload = function() {
    alert("some svg loaded");
}
我认为可以肯定地说,如果您假设浏览器能够显示嵌入式 SVG,那么您可以确定它也能实现addEventListener
2021-03-21 02:45:48
svgholder.load("image/svg+xml", function()...似乎是在调用 jquery ajax 加载。在 v3.0 之前,jquery 根据提供的参数确定要调用的负载。使用第一个参数中的字符串,jquery 尝试将 'image/svg+xml' 作为 url 执行 GET。由于它将加载的内容放置在所选元素中,然后调用提供的回调,这可能看起来像加载通知一样工作,但它正在做其他事情。在您的控制台中查找 404。此外,.load 事件处理程序自 3.0 起已弃用。
2021-03-21 02:45:48
注意:考虑使用addEventListener('load', handler)而不是设置onload属性以确保不会覆盖其他加载处理程序。但是,古代浏览器不支持此功能。 问题: jQueryload是我尝试使用的第一种方法,但如果没有'image/svg+xml'作为第一个参数,它将无法工作。你能解释一下这个魔法吗?我在 jQuery 文档中找不到解释。它只是将参数提到为url(这里我们给出了一个 MIME 类型)。再说一次,为什么我们不需要这样的东西onload呢?
2021-04-02 02:45:48

假设你的 SVG 在一个<embed>标签中:

<embed id="embedded-image" src="image.svg" type="image/svg+xml" />

SVG 图像本质上位于一个子文档中,该子文档将具有load与主document. 但是,您可以侦听此事件并对其进行处理:

var embed = document.getElementById("embedded-image");
embed.addEventListener('load', function()
{
    var svg = embed.getSVGDocument();
    // Operate upon the SVG DOM here
});

这比轮询要好,因为您对 SVG 所做的任何修改都会在首次​​绘制之前发生,从而减少闪烁和 CPU 绘制所花费的精力。

要在给定元素上使用 JQuery 执行以下操作: var svg = $(embed.getSVGDocument().documentElement);
2021-03-18 02:45:48

嵌入元素(例如对象)的加载事件将是我的偏好,但是,如果由于某种原因这不是一个可行的解决方案,那么我为 SVG DOM 找到的唯一通用且可靠的测试是 SVG 的 getCurrentTime 方法根元素:

var element = document.getElementById( 'elementId' );
var svgDoc = element.contentDocument;
var svgRoot = svgDoc ? svgDoc.rootElement : null;

if ( svgRoot
    && svgRoot.getCurrentTime
    && ( svgRoot.getCurrentTime() > 0 ))
{
    /* SVG DOM ready */
}

W3C的SVG建议指出getCurrentTime上SVGSVGElement:

返回相对于当前 SVG 文档片段的开始时间的当前时间(以秒为单位)。如果在文档时间线开始之前调用 getCurrentTime(例如,在分派文档的 SVGLoad 事件之前通过在 'script' 元素中运行的脚本),则返回 0。

使用 jQuery,您可以绑定到 Erik 提到的窗口加载事件:

$(window).load(function(){
    var svg = document.getElementById("chart").getSVGDocument();
});
我想通过这种方式你可以知道html页面中何时加载了SVG对象,但你仍然不知道SVG的DOM是否准备好了。
2021-03-30 02:45:48
当我将 jquery 嵌入到独立的 SVG 中时,我发现它可以工作 - 谢谢!
2021-03-31 02:45:48