如何验证背景(CSS)图片是否已加载?

35

我有一个如下的CSS类,我要将其应用到一个<td>标签上:

.bg {
   background-image: url('bg.jpg');
   display: none;
}

如何使用JavaScript/jQuery判断背景图像是否已经加载完成?

6个回答

60
我所知道的唯一方法是使用 JavaScript 加载图像,然后将该图像设置为背景。

例如:

var bgImg = new Image();
bgImg.onload = function(){
   myDiv.style.backgroundImage = 'url(' + bgImg.src + ')';
};
bgImg.src = imageLocation;

由于某种奇怪的原因,仅当imageLocation实际上需要一些时间来加载时,例如从网络加载时,才会触发onload事件。在本地测试中不起作用,因为加载时间为0。 - thedp
2
你可以为 bgImg.src = imageLocation; 设置一个超时时间,但我想大多数人不会使用你的电脑。 :P - Dan Beam
这段代码存在一个bug,当bgImg.src包含单引号、双引号和反斜杠等特殊字符时会出现问题。相反,你应该使用'url("' + bgImg.src.replace("\\", "\\\\").replace('"', '\\"') + '")';来代替。我认为这样可以正确地转义任何URL。 - David Goldstein
我在想,在将URL分配给背景图像后,是否明智地将bgImg = null;设置为null,因为JS对象实际上并不需要。担心的是浏览器可能会有两个副本并浪费内存?这肯定取决于具体实现。 - quickshiftin
这将尝试两次获取图像,希望浏览器缓存可以防止第二次获取实际调用服务器。 - Ben Winding

4

在初始页面加载时,将类赋予一个带有visibility:hidden的div。这样,在您将类分配给表格单元格时,它已经在浏览器缓存中了。


2

这篇文章可能会对您有所帮助。相关章节:

// Once the document is loaded, check to see if the
// image has loaded.
$(
    function(){
        var jImg = $( "img:first" );

        // Alert the image "complete" flag using the
        // attr() method as well as the DOM property.
        alert(
            "attr(): " +
            jImg.attr( "complete" ) + "\n\n" +

            ".complete: " +
            jImg[ 0 ].complete + "\n\n" +

            "getAttribute(): " +
            jImg[ 0 ].getAttribute( "complete" )
        );
    }
);

基本上选择背景图像并检查其是否加载。


当背景的初始状态为display:none;时,我认为这是无法完成的。 - thedp

2

@Jamie Dixon - 他并没有说他想对背景图片做任何事情,只是想知道它何时加载完成...

$(function( )
{
    var a = new Image;
    a.onload = function( ){ /* do whatever */ };
    a.src = $( 'body' ).css( 'background-image' );
});

如果我应用背景的元素具有属性 - display:none;,它会起作用吗? - thedp
是的,据我所知这并不重要,它只是获取样式规则并强制预加载图像(本质上),当它完成预加载时会触发onLoad事件。但是,如果您想延迟加载大型图像,则不应这样做(因为它可能会减慢加载速度)。 - Dan Beam
我在努力让它工作。 这是我的样式:background-image: url('../Images/bg/xxx.jpg'); a.src 给出了带有 url('') 的图像位置。似乎 onLoad 从未触发。(我也尝试过 onload) - thedp
嘿,thedp,我刚刚编辑了我的代码。虽然我发帖时它是可以工作的,但对我来说它现在不起作用了。请尝试新版本。 - Dan Beam

1

onload存在的一个问题是它在数据准备好时就触发了,而不是在完成渲染时触发。

对于一个项目,我加载了许多中等大小的图像。当图像正在加载时,会出现图像“突然出现”的效果

通过使用onloaddecode的组合解决了这个问题。

至于问:如何判断背景图像是否加载完成?这可以有几种解释;但如果你想要判断是否完成渲染,那么这是一个攻击该问题的方法。

简化版:


img.onload = () => {
    some_elm.style.backgroundImage = 'url(' + some_src + ')';
    img.decode().then(some_function).catch(some_function);
}
img.onerror = some_function;
img.src = some_src;

在其中 some_function 只是检查所有加载的图像上的计数器,但当然也可以用于 一个 图像。

猜想可能是 decode() 的开销导致它流畅,但已经非常好地工作了。

发现它对于加载 <img> 元素(仅使用 decode)和背景(onload + decode)都很有效。


然后可以做任何事情,从简单地向包装器添加类到添加一些花哨的效果 - 例如以有序方式逐个淡入图片等。

还要注意 浏览器兼容性,针对 decode()


0

你也可以提供一个函数,简单地将img标签替换为div/background,这样你就可以同时受益于onload属性和div的灵活性。

当然,你可以微调代码以最好地满足你的需求,但在我的情况下,我还确保宽度或高度被保留,以更好地控制我期望的内容。

我的代码如下:

<img src="imageToLoad.jpg" onload="imageLoadedTurnItAsDivBackground($(this), true, '')">

<style>
.img-to-div {
    background-size: contain;
}
</style>

<script>
// Background Image Loaded
function imageLoadedTurnItAsDivBackground(tag, preserveHeight, appendHtml) {

    // Make sure parameters are all ok
    if (!tag || !tag.length) return;
    const w = tag.width();
    const h = tag.height();

    if (!w || !h) return;

    // Preserve height or width in addition to the image ratio
    if (preserveHeight) {
        const r = h/w;
        tag.css('width', w * r);
    } 
    else {
        const r = w/h;
        tag.css('height', h * r);
    }
    const src = tag.attr('src');

    // Make the img disappear (one could animate stuff)
    tag.css('display', 'none');

    // Add the div, potentially adding extra HTML inside the div
    tag.after(`
        <div class="img-to-div" style="background-image: url(${src}); width: ${w}px; height:${h}px">${appendHtml}</div>
    `);

    // Finally remove the original img, turned useless now
    tag.remove();
}
</script>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接