使用JavaScript&amp ;;预加载图像jQuery的

时间:2009-09-20 17:24:08

标签: javascript jquery

我正在使用以下代码将一些HTML插入到div中,并预加载该HTML中可能包含的任何图像(html var的数据实际上是从实际代码中的AJAX请求中获取的)。这是为了防止浏览器在显示div(使用slideDown事件)时加载获取的HTML图像 - 因为这会导致效果的流动性在转换中加载图像时被破坏。我想我可以使用隔行扫描的JPEG,这样几乎可以立即知道图像的尺寸,但显然可以找到更清晰的方法。 :P

var html = '<img src="images/test.jpg" alt="test" />';

$('div.content').hide().html(html);

$('div.content img').each(function(){

    var img = new Image();

    img.src = $(this).attr('src');

    $(this).attr('src', img.src);

});

$('div.content').slideDown('normal');

我正在使用Image对象及其后续分配,根据给出here的建议,但不幸的是,浏览器使用此方法仍未缓存图像,因为sildeDown()效果仍然被中断当图像加载时。

任何帮助或替代方法?非常感谢。

编辑 - 09年9月21日


进展!原来浏览器缓存图像,我只是没有给它时间这样做(它只需要一秒加载alert()或setInterval())。现在介绍可能是最混乱的代码 - 我使用无限循环来创建暂停。

新方法通过将函数(将每个图像的src添加到数组)绑定到该图像的成功加载事件来扩展上面的旧代码。然后它会在等待所有图像加载并因此出现在数组中时陷入无限循环。这似乎可以作为同步预加载图像的一种方式 - 但问题仍然存在;某些原因的while()循环甚至在所有图像都被加载后无限循环,除非我添加一个alert()来暂停它。

新代码:

var html = '<img src="images/test.jpg" alt="test" />';

$('div.content').hide().html(html);

// define usr variables object
$.usrvar = {};

// array of loaded images' urls
$.usrvar.images = [];

// boolean for whether this content has images (and if we should check they are all loaded later)
$.usrvar.hasimages = false;

// foreach of any images inside the content
$('div.content img').each(function(){

    // if we're here then this content has images..
    $.usrvar.hasimages = true;

    // set this image's src to a var
    var src = $(this).attr('src');

    // add this image to our images array once it has finished loading
    $(this).load(function(){

        $.usrvar.images.push(src);

    });

    // create a new image
    var img = new Image();

    // set our new image's src
    img.src = src;

});

// avoid this code if we don't have images in the content
if ($.usrvar.hasimages != false) {

    // no images are yet loaded
    $.usrvar.imagesloaded = false;

    // repeatedly cycle (while() loop) through all images in content (each() loop)
    while ($.usrvar.imagesloaded != true) {

        $('div.content img').each(function(){

            // get this loop's image src
            var src = $(this).attr('src');

            // if this src is in our images array, it must have finished loading
            if ($.usrvar.images.indexOf(src) != -1) {

                // set imagesloaded to trueai
                $.usrvar.imagesloaded = true;

            } else {

                // without the pause caused by this alert(), this loop becomes infinite?!
                alert('pause');

                // this image is not yet loaded, so set var to false to initiate another loop
                // (ignores whether imagesloaded has been set to true by another image, because ALL
                // need to be loaded
                $.usrvar.imagesloaded = false;

            }

        });

    }

}

$('div.content').slideDown('normal');

4 个答案:

答案 0 :(得分:1)

我做了以下解决方案,但尚未经过测试,因此您已收到警告;)

// HTML (any formatting possible)
// no src for the images: it is provided in alt which is of the form url::actualAlt
var html = "<p><img alt='images/test.jpg::test' /><br />Some Text<br /><img alt='images/test2.jpg::test2' /></p>";

$(document).ready(function() {

    // Reference to the content div (faster)
    var divContent = $("div.content");

    // Hide the div, put the HTML
    divContent.hide().html(html);

    // Webkit browsers sometimes do not parse immediately
    // The setTimeout(function,1) gives them time to do so
    setTimeout(function() {

        // Get the images
        var images = $("img",divContent);

        // Find the number of images for synchronization purpose
        var counter = images.length;

        // Synchronizer
        // will show the div when all images have been loaded
        function imageLoaded() {
            if (--counter<=0) $('div.content').slideDown('normal');
        }

        // Loading loop
        // For each image in divContent
        $.each(images,function() {
            // Get the url & alt info from the alt attribute
            var tmp = $(this).attr("alt").split("::");
            // Set the alt attribute to its actual value
            $(this).attr("alt",tmp[1]);
            // Wire the onload & onerror handlers
            this.onload = this.onerror = imageLoaded;
            // Set the image src
            this.src = tmp[0];
        });

    },1);

});

答案 1 :(得分:0)

创建一个间隔/超时并让它检查你的compterGenerated css-height,如果它是自动调整的,它将从0开始并结束到100(例如)。但是在Safari中,它会在图像之前加载高度,因此它可能无法在所有浏览器中运行...

答案 2 :(得分:0)

我正在玩这个,我创建了一个稍微不同的解决方案。不是在加载数据时将图像推送到数组上,而是将它们全部推送到循环中的数组上,然后在加载事件中将它们从数组中删除并调用“完成”函数。它检查图像数组是否为空,如果是,则清除并显示内容。

var html = '< animg src="images/test.jpg" alt="test" />'; // not allowed to post images...

$('div.content').hide().html(html);

// preload images

// define usr variables object
$.usrvar = {};      
// array of loaded images' urls
$.usrvar.images = [];
// initially no images      
$.usrvar.hasimages = false;
$('div.content img').each(function() {
    // if we're here then this content has images..
    $.usrvar.hasimages = true;
    // set this image's src to a var
    var src = this.src;
    // add this image to our images array
    $.usrvar.images.push(src);
    // callback when image has finished loading
    $(this).load(function(){
        var index = $.usrvar.images.indexOf(src);
        $.usrvar.images.splice(index,1);
        finish_loading();
    });
    // create a new image
    var img = new Image();
    // set our new image's src
    img.src = src;
});
if(!$.usrvar.hasimages) finish_loading();

function finish_loading() {
    if($.usrvar.hasimages) {
        if($.usrvar.images.length > 0) return;
    }
    $('div.content').slideDown('normal');
}

编辑:看看朱利安的帖子,他的方法更好。我的方法以类似的方式工作,但是像原始解决方案一样通过一系列srcs跟踪图像而不仅仅是一个计数(这更有效)。

编辑2:我认为这是一个更好的解决方案,但它似乎对我不起作用。也许与负载事件被调用太接近彼此有关。有时它会工作,但有时它会在加载图像时挂起,图像计数器永远不会达到零。我已经回到上面帖子中的方法了。

编辑3:看起来是造成问题的setTimeout。

答案 3 :(得分:0)

这就是我使用的。正如你从我的观点中看到的那样,我不是专业人士,但我发现它在某个地方并且它对我来说很有用,并且看起来比发布的所有内容都简单得多。也许我错过了一个要求。 :)

    var myImgs = ['images/nav/img1.png', 'images/nav/img2.png', 'images/nav/img3.png', 'images/nav/img4.png', 'images/expand.png', 'images/collapse.png'];

    function preload(imgs) {
        var img;
        for (var i = 0, len = imgs.length; i < len; ++i) {
            img = new Image();
            img.src = imgs[i];
        }
    }

    preload(myImgs);