【问题标题】:Automatic HTML preloader自动 HTML 预加载器
【发布时间】:2010-07-10 05:56:43
【问题描述】:

我有一个使用 ajax 加载 HTML 块的页面。所有这些片段都将具有图像,其中一些将使用 background-image 在单独的 CSS 中指定。我想编写一个预加载器,以便加载的块只有在所有加载完成后才会显示。如果所有图像都在 HTML 块中,我将加载它,将其放入隐藏元素中,然后查找所有 img 标签并控制它们是否已加载(或在加载方法中放置一些回调)。问题是 CSS 我不能那么容易地做到这一点......所以我想到的唯一方法是拥有一个包含所有图像位置的单独 xml 文件,并使用它来创建 IMG 元素,加载它们以及它们何时是加载显示块(因此图像已经从服务器中提取)。你知道更好的方法吗?有没有现成的组件?

【问题讨论】:

    标签: html ajax image preloader


    【解决方案1】:

    如果您接受一条建议,请不要这样做。这里的优先级是内容,图像是次要的。不要因为图像而让用户等待内容。这会让人头疼,尤其是在连接速度较慢的情况下。

    最好的办法是使用一些占位符/指示符图像来提供有关加载组件的反馈,并且可能对<img> 标签中的图像使用一些不错的淡入淡出效果。

    注意:对于小图像,您可以尝试Data: URIs,它允许您将图像嵌入到 HTML 或 CSS 文件中。


    更新

    永远不要说不。 :) 这是您可以使用的原型。它在 FF 3+​​ 和 IE 5.5+ 中对我来说很好,但由于某种原因,Chrome 显示 cssRules 为空。我必须弄清楚为什么。另一个 TODO 是在 IE 中合并 @import-ed 规则,因为它不能与标准规则集一起使用。

    无论如何,如您所见,您需要传递一个document、一个callback 并且有一个可选 timeout 参数(默认为10 秒)。

    callback 将在文档中的每个图像加载后执行。 (请注意,如果它因 404 失败,脚本会处理它)。在这里你可以做你的fadeIn或show之类的。

    timeout 是作为备用的,如果出现任何问题,它会在一定时间后调用回调。

    // this function will execute a callback after all
    // images has been loaded in a document
    function imageLoader(document, callback, timeout) {
    
        timeout = timeout || 10000; // 10s default
        var i, j, remaining = 0;    // number of loading images
        // hash table to ensure uniqueness
        // url => image object
        var imgs = {};
    
        function handler(el, event) {
            remaining -= 1;
            if (remaining == 0 && !callback.done
             && typeof callback === "function") {
                callback.done = true;
                callback();
            }
        }
    
        // adds the image to the hash table
        function addImage(src, img) {
            if (!imgs[src]) {
              remaining++;
              img = img || new Image();
              img.onload  = handler;
              img.onerror = handler;
              img.src = img.src || src;
              // add to the hash table
              imgs[src] = img;
            }
        }
    
        // now gather all those images
        var sheets = document.styleSheets;
        for (i=0; i<sheets.length; i++) {
    
            // HTML <img> tags
            var els = document.getElementsByTagName("IMG");
            for (i=0; i<els.length; i++) {
                var el = els[i].src;
                addImage(el.src, el);
            }
    
            // CSS background images
            var css = sheets[i];
            var pos = css.href.lastIndexOf("/");
            var cssDir = (pos != -1) ? css.href.substring(0, pos + 1) : "";
            var rules  = css.cssRules || css.rules;
    
            for (j=0; j<rules.length; j++) {
                var style = rules[j].style;
                var img = style.backgroundImage;
                if (img == "none") img = "";
                var filename = img.substring(4, img.length - 1).replace(/['"]/g,"");
                if (filename) {
                    if (filename.indexOf("http://") != 0
                     && filename.indexOf("/") != 0) {
                        filename = cssDir + filename;
                    }
                    addImage(filename);
                }
            }
        }
    
        // correct the start time
        var start = +new Date();
    
        var timer = setInterval(function(){
            var elapsed = +new Date() - start;
            // if timout reached and callback
            // hasn't been not called yet
            if (elapsed > timeout && !callback.done) {
                callback();
                callback.done = true;
                clearInterval(timer);
            }
        }, 50);
    }
    

    【讨论】:

    • 通常我会同意你的看法。但这次我真的需要一个显示进度的页面,只有在一切都完成后才能继续。
    • 嗯,很好的解决方案......即使我不知道可以在 Js 中通读 CSS(我是懒人......)。我认为这很好,但是由于我通常只有一个 Css 并且我从服务器获取 HTML 数据,因此我需要通过匹配实际使用我加载的 HTML 中的规则的元素来增加一些复杂性...... .而且我认为这不会很容易,因为规则的复杂性。无论如何,如果我可以让设计人员为每个加载的 HTML 块编写一个 CSS,我可以使用这种方法。这是一个很好的起点。
    • 对不起,我已经出去几天了:D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    相关资源
    最近更新 更多