【问题标题】:How can I check if a background image is loaded?如何检查是否加载了背景图像?
【发布时间】:2011-02-20 15:35:12
【问题描述】:

我想在 body 标签上设置背景图片,然后运行一些代码 - 像这样:

$('body').css('background-image','http://picture.de/image.png').load(function() {
    alert('Background image done loading');
    // This doesn't work
});

如何确保背景图片已完全加载?

【问题讨论】:

  • 只需将相同的 URL 分配给具有 onload 事件的 Image() 对象。
  • 确保将 css url 包裹在 url()
  • Imagesloaded 会做这样的事情imagesloaded.desandro.com

标签: javascript jquery


【解决方案1】:

试试这个:

$('<img/>').attr('src', 'http://picture.de/image.png').on('load', function() {
   $(this).remove(); // prevent memory leaks as @benweet suggested
   $('body').css('background-image', 'url(http://picture.de/image.png)');
});

这将在内存中创建一个新图像并使用 load 事件来检测 src 何时加载。

编辑: 在 Vanilla JavaScript 中它可能如下所示:

var src = 'http://picture.de/image.png';
var image = new Image();
image.addEventListener('load', function() {
   body.style.backgroundImage = 'url(' + src + ')';
});
image.src = src;

它可以被抽象成返回一个promise的方便函数:

function load(src) {
    return new Promise((resolve, reject) => {
        const image = new Image();
        image.addEventListener('load', resolve);
        image.addEventListener('error', reject);
        image.src = src;
    });
}

const image = 'http://placekitten.com/200/300';
load(image).then(() => {
   body.style.backgroundImage = `url(${image})`;
});

【讨论】:

  • 好像图片会无缘无故加载两次。
  • @gAMBOOKa 它们被加载一次,因为它们保留在浏览器内存中。这也是一样的,当你把隐藏的图片放在页面顶部,然后在 CSS 中设置它——所以图片在 css 文件之前开始下载——这叫做预加载。
  • 我不太确定,但我认为您指的是缓存。我不认为存储资产的浏览器内存之类的东西。如果您指的是缓存,请记住您正在添加一个额外的 HTTP 请求,并且所有客户端可能都没有启用缓存。
  • 在任何有 jquery 的页面中输入这个:javascript:void($('&lt;img/&gt;').attr('src', 'http://farm6.static.flickr.com/5049/5220175127_5693faf952.jpg').load(function() { $('html').css('background-image', 'url(http://farm6.static.flickr.com/5049/5220175127_5693faf952.jpg)'); })) 并在 Firebug 中检查 HTTP 请求。如果我在另一个选项卡中打开了此图像的闪烁页面,它不会执行任何 HTTP 请求,只需立即显示此图片。当我清除缓存并运行它时,有一个请求。
  • this testthis one 之间的比较表明您必须在$('&lt;img/&gt;') 对象上调用.remove() 以避免内存泄漏。您应该在第一次测试中看到稳定的内存消耗,在第二次测试中看到内存增加。在 Chrome 28 上运行几个小时后,第一次测试需要 80MB,第二次需要 270MB。
【解决方案2】:

我有一个名为waitForImagesjQuery plugin,它可以检测下载背景图像的时间。

$('body')
  .css('background-image','url(http://picture.de/image.png)')
  .waitForImages(function() {
    alert('Background image done loading');
    // This *does* work
  }, $.noop, true);

【讨论】:

  • 这个插件也非常适合使用each回调来显示加载进度。
  • @alex,我应该如何检查类中每个元素的每个背景图像?我试过这个,但似乎没有做对。 $('.user_main_photo_thumb').waitForImages(function() { $(this).parents('.photoThumbFrame').delay(1000).slideDown(); }, function(loaded, count, success) { });
  • @Relm 你没有正确使用它。第二个回调是每个图像。另外,delay() 也不能这样工作。
【解决方案3】:

没有针对 CSS 资源的 JS 回调。

【讨论】:

【解决方案4】:

类似这样的:

var $div = $('div'),
  bg = $div.css('background-image');
  if (bg) {
    var src = bg.replace(/(^url\()|(\)$|[\"\'])/g, ''),
      $img = $('<img>').attr('src', src).on('load', function() {
        // do something, maybe:
        $div.fadeIn();
      });
  }
});

【讨论】:

  • 你好……这似乎可行,尽管我将 bg.replace 设置为 bg.replace( ... , my_src )。但我的问题是:一旦 $('') 加载,&lt;img&gt; 究竟会发生什么......我的意思是它实际上并不是真实的 - 它只是一个虚拟的占位符,对吗?
  • 对。 &lt;img&gt; 永远不会插入到 DOM 中;它只是用来“欺骗”浏览器将图像文件加载到缓存中。
  • 如果你不想调用 jQuery 会有帮助
【解决方案5】:

纯 JS 解决方案,将添加预加载器、设置背景图像,然后将其设置为垃圾收集以及它的事件侦听器

短版:

const imageUrl = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png";
let bgElement = document.querySelector("body");
let preloaderImg = document.createElement("img");
preloaderImg.src = imageUrl;

preloaderImg.addEventListener('load', (event) => {
    bgElement.style.backgroundImage = `url(${imageUrl})`;
    preloaderImg = null;
});

更长一点的不透明度过渡:

const imageUrl = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png";
let bgElement = document.querySelector(".bg-lazy");
bgElement.classList.add("bg-loading");
let preloaderImg = document.createElement("img");
preloaderImg.src = imageUrl;

preloaderImg.addEventListener('load', (event) => {
  bgElement.classList.remove("bg-loading");
  bgElement.style.backgroundImage = `url(${imageUrl})`;
  preloaderImg = null;
});
.bg-lazy {
  height: 100vh;
  width: 100vw;
  transition: opacity 1s ease-out;
}

.bg-loading {
  opacity: 0;
}
&lt;div class="bg-lazy"&gt;&lt;/div&gt;

【讨论】:

  • 被低估的解决方案。
  • @TomThomson 感谢 Tom,我发现图像转换无法正常工作,已修复
  • 这是一个很好的答案。
  • 有趣的解决方案。您如何看待使用&lt;link&gt; 标签进行预加载:
  • @bytangle 这将增加很少需要的加载优先级
【解决方案6】:

这是我制作的一个小插件,可以让你做到这一点,它也适用于多个背景图像和多个元素:

阅读文章:

http://catmull.uk/code-lab/background-image-loaded/

或者直接看插件代码:

http://catmull.uk/downloads/bg-loaded/bg-loaded.js

所以只需包含插件,然后在元素上调用它:

<script type="text/javascript" src="http://catmull.uk/downloads/bg-loaded/bg-loaded.js"></script>
<script type="text/javascript">
   $('body').bgLoaded();
</script>

显然下载插件并将其存储在您自己的主机上。

默认情况下,一旦背景被加载,它会为每个匹配的元素添加一个额外的“bg-loaded”类,但您可以通过向它传递一个不同的函数来轻松更改它:

<script type="text/javascript" src="http://catmull.uk/downloads/bg-loaded/bg-loaded.js"></script>
<script type="text/javascript">
   $('body').bgLoaded({
      afterLoaded : function() {
         alert('Background image done loading');
      }
   });
</script>

这是一个演示它工作的代码笔。

http://codepen.io/catmull/pen/Lfcpb

【讨论】:

    【解决方案7】:

    我找到了一个对我来说效果更好的解决方案,它的优点是可以用于多个图像(此示例中未说明情况)。

    来自@adeneo 对this question 的回答:

    如果你有一个带有背景图片的元素,像这样

    <div id="test" style="background-image: url(link/to/image.png)"><div>
    

    您可以通过获取图像 URL 来等待背景加载,然后 将它用于带有 onload 处理程序的 javascript 中的图像对象

    var src = $('#test').css('background-image');
    var url = src.match(/\((.*?)\)/)[1].replace(/('|")/g,'');
    
    var img = new Image();
    img.onload = function() {
        alert('image loaded');
    }
    img.src = url;
    if (img.complete) img.onload();
    

    【讨论】:

      【解决方案8】:

      我做了一个纯 javascript hack 来使这成为可能。

      <div class="my_background_image" style="background-image: url(broken-image.jpg)">
      <img class="image_error" src="broken-image.jpg" onerror="this.parentElement.style.display='none';">
      </div>
      

      或者

      onerror="this.parentElement.backgroundImage = "url('image_placeHolder.png')";
      

      css:

      .image_error {
          display: none;
      }
      

      【讨论】:

        【解决方案9】:

        https://github.com/alexanderdickson/waitForImages

        $('selector').waitForImages({
            finished: function() {
               // ...
            },
            each: function() {
               // ...
            },
            waitForAll: true
        });
        

        【讨论】:

          【解决方案10】:

          这是一个简单的香草黑客〜

          (function(image){
            image.onload = function(){ 
                             $(body).addClass('loaded-background');
                             alert('Background image done loading');
                             // TODO fancy fade-in
                           };
            image.src    = "http://picture.de/image.png";
          })(new Image());
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-12-24
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多