【问题标题】:jQuery loaded html content - Check if images are loaded and renderedjQuery 加载的 html 内容 - 检查图像是否已加载和渲染
【发布时间】:2015-05-03 00:00:56
【问题描述】:

我有标签逻辑,可以在包装器中加载 html 模板。这很好用,但我包含了一个动画,当切换选项卡时,它会为选项卡包装器的 height 设置动画。

问题如下:当模板包含<img src="/some-image.png"> 时,$('#tab-content').load('template-url', function() {...}) 回调函数有时会在浏览器显示图像之前执行。而且我的动画不能正常工作。

Code example (jsFiddle):

var currentHeight = $contentHolder.height();

$contentHolder.load(path, function() {
    $contentHolder.stop();

    function animateHeight() {
        var loadedContentHeight = $contentHolder.css('height', 'auto').height();
        $contentHolder.height(currentHeight);
        $contentHolder.animate({
            height: loadedContentHeight
        }, 800, 'linear');
    }
    animateHeight();
});

我尝试设置小超时,但并非每次都有效。如果我设置超过 300 毫秒的超时时间,感觉标签更改太慢了。

我尝试在$('img').load(function() {}) 被触发时执行动画,但没有成功。

当网页完全刷新并且第一次加载每个标签内容时,最常发生此错误。

【问题讨论】:

标签: javascript jquery animation asynchronous dom-events


【解决方案1】:

load 事件的图像有点坏了。要知道图像何时加载,您必须观察 DOM 的变化。然后在每次更改时,您都必须获取所有新图像并从回调中将onload 事件添加到它们。为了防止每次都检查每个元素,一旦它们被加载,您可以通过添加 data-loaded="true" 属性来标记它们。


监听 DOM 变化的一种方法是 MutationObserver 事件。 all modern browsers and IE11 支持这一点。

可以在此答案中找到更好的支持解决方案(IE9 及更高版本):Detect changes in the DOM。我不会在这里重复它(但它包含在下面的演示中)。


在每次 DOM 更改时,首先通过检查 element.complete 检查是否已经加载了没有 data-loaded 属性的图像(当图像仍在浏览器的缓存中时可能发生这种情况)。如果是这样,请触发回调函数并向其添加属性。

如果.complete 不是这种情况,请向它们添加一个onload 事件,该事件也会在加载后触发回调。

在您的情况下,您只想在加载所有图像时触发回调,所以我添加了一个检查是否有没有 data-loaded 属性的静止图像。如果您删除该 if 子句,您的回调将在每个图像加载后运行。

// Observe the DOM for changes
observeDOM(document.body, function(){ 
    checkNewImages();
});

var checkNewImages = function() {
    var images = $('img:not([data-loaded]').each(function() {
        addImageLoadedEvent( this );
    });
}

var addImageLoadedEvent = function(img) {
    if (img.complete) {
        onImageLoaded(img);
    } else {
        $(img).on('load', function() {
            onImageLoaded(this);   
        });
    }
}

// The callback that is fired once an element is loaded
var onImagesLoaded = function(img) {
    $(img).attr('data-loaded', 'true');

    if($('img:not([data-loaded])').length === 0) {

        // YourCallbackHere();

    }
}

演示:fire event on all images loaded

【讨论】:

  • 为了完整起见,还有一个 jQuery 插件可以做类似的事情:waitForImages
【解决方案2】:

您可以调用 animateHeight 函数,因为加载的 HTML 中的每个图像都会依次加载。如果您有其他对象(例如视频),则可以展开此选择。

// Call animateHeight as each image loads
var items = $('img', $contentHolder);
items.bind('load', function(){ 
    animateHeight();
});

更新的演示:http://jsfiddle.net/jxxrhvvz/1/

【讨论】:

  • 感谢您的回答,我将使用您的代码来解决我的问题。我接受了另一个答案,因为它与主题 heading 更相关并提供更多解释。对于我的小项目,我需要一些简单的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-29
  • 1970-01-01
  • 2021-08-08
  • 2016-01-20
  • 1970-01-01
  • 1970-01-01
  • 2014-11-30
相关资源
最近更新 更多