15

我正在开发一个带有 5 个左右隐藏 div 的基于 jquery 的主页,每个 div 都包含几个背景 css 图像。

问题是浏览器在显示父图层的可见性之前不会将 css 图像加载到 DOM 中,导致当图层可见时图像会缓慢加载。

我已经考虑过的解决方案:

  • CSS sprites(为此重新设计的工作量太大,并且在显示/隐藏 div 时不会真正起作用)
  • 这个自动加载 CSS 背景图像的 jQuery 插件(正如许多其他人所报告的那样,对我来说根本不起作用)。
  • 通过js预加载图片:

    $(function() {
    function preloadImg(image) {
      var img = new Image();
      img.src = image;
    }
    
    preloadImg('/images/home/search_bg_selected.png');
    });
    

    该解决方案似乎将图像加载到 dom 中两次...一次在 js 加载它时,然后在加载它的 div 层变得可见时再次...所以它进行了 2 个 HTTP 调用,因此无法正常工作。

我缺少的这个问题的任何其他解决方案?

4

5 回答 5

13

当您说其他方式时,您是指不使用 Javascript 的方式吗?

<script language="JavaScript">
function preloader() 
{
     // counter
     var i = 0;

     // create object
     imageObj = new Image();

     // set image list
     images = new Array();
     images[0]="image1.jpg"
     images[1]="image2.jpg"
     images[2]="image3.jpg"
     images[3]="image4.jpg"

     // start preloading
     for(i=0; i<=3; i++) 
     {
          imageObj.src=images[i];
     }
} 
</script>

其他无 JS 方法是将一些 html 放置在页面中的某个位置,这样就不会被看到:

<image src="picture.jpg" width="1" height="1" border="0">

或 HTML...

<img src="images/arrow-down.png" class="hiddenPic" />

...和CSS ...

.hiddenPic {
    height:1px;
    width:1px;
}

更多 JavaScript 方法:

function preload(images) {
    if (document.images) {
        var i = 0;
        var imageArray = new Array();
        imageArray = images.split(',');
        var imageObj = new Image();
        for(i=0; i<=imageArray.length-1; i++) {
            //document.write('<img src="' + imageArray[i] + '" />');// Write to page (uncomment to check images)
            imageObj.src=images[i];
        }
    }
}

然后使用类似的方式加载图像:

<script type="text/javascript">
preload('image1.jpg,image2.jpg,image3.jpg');
</script>
于 2009-11-24T02:14:36.330 回答
7

像其他解决方案一样,硬编码 URL 建议对代码维护征税。避免这种情况并使用 jQuery 制定通用解决方案相对容易。

此函数选择所有隐藏元素,检查它们是否有背景图像,然后将它们加载到隐藏的虚拟元素中。

$(':hidden').each(function() {
  //checks for background-image tab
  var backgroundImage = $(this).css("background-image");
  if (backgroundImage != 'none') {
    var imgUrl = backgroundImage.replace(/"/g,"").replace(/url\(|\)$/ig, "");
    $('<img/>')[0].src = imgUrl;
  }
});
于 2012-02-07T15:05:04.970 回答
7

CSS 预加载很容易。

示例

body:after{
    display:none;
    content: url(img01.png) url(img02.png) url(img03.png) url(img04.png)
}
于 2013-01-17T23:41:25.610 回答
3

浏览器开始支持元素的属性prefetchpreload属性。<link>rel="..."

Addy Osmani关于 preload 和 prefetch 属性的文章非常好,并描述了何时应该使用它们:

预加载是向浏览器发出的早期获取指令,以请求页面所需的资源(关键脚本、Web 字体、主图像)。

Prefetch 服务于一个稍微不同的用例——用户未来的导航(例如在视图或页面之间),其中获取的资源和请求需要在导航中持续存在。如果页面 A 对页面 B 所需的关键资源发起预取请求,则关键资源和导航请求可以并行完成。如果我们为此用例使用预加载,它将在页面 A 的卸载时立即取消。

该元素的使用方式如下:

<link rel="preload" as="image" href="https://your.url.com/yourimage.jpg" />

我正在设计一个包含多个步骤的表单,每个步骤都有不同的背景图像。当 Chrome 下载下一个背景图像时,此模式可解决步骤之间的“闪烁”问题。

于 2017-10-16T19:37:17.060 回答
2

“这个解决方案似乎将图像加载到 dom 中两次......一次是在 js 加载它时,然后再次在加载它的 div 层变得可见时......所以它进行了 2 个 http 调用,因此无法正常工作”

第二个 http 请求应该以 304 响应(未修改),所以我想这可以吗?另一种选择是通过 jQuery 加载图像,然后通过 DOM 作为背景图像内联插入,例如:

jQuery.fn.insertPreload = function(src) {
    return this.each(function() {
        var $this = $(this);
        $(new Image()).load(function(e) {
            $this.css('backgroundImage','url('+src+')');
        }).attr('src',src);
    });
};

$('div').insertPreload('[huge image source]');
于 2009-11-24T02:41:47.943 回答