如何创建一个JavaScript回调来知道何时加载图像?


Answers:


159

.complete +回调

这是一种符合标准的方法,没有任何额外的依赖关系,并且等待的时间不再必要:

var img = document.querySelector('img')

function loaded() {
  alert('loaded')
}

if (img.complete) {
  loaded()
} else {
  img.addEventListener('load', loaded)
  img.addEventListener('error', function() {
      alert('error')
  })
}

资料来源:http : //www.html5rocks.com/en/tutorials/es6/promises/


4
如果图像在img.complete通话和addEventListener通话之间完成,这会出错吗?
托马斯·阿勒

@ThomasAhle我不是专家,但这似乎有可能。让我们看看是否有人有解决方案。
Ciro Santilli郝海东冠状病六四事件法轮功

我想这只能是并行代码的问题,其中大部分的JavaScript可能不是..
托马斯AHLE

4
@ThomasAhle不能,因为浏览器只会在事件队列旋转时才触发load事件。就是说,load事件侦听器必须位于else子句中,img.complete这样才能在load触发事件之前变为true ,因此,如果不是,则您可能会loaded调用两次(请注意,这相对可能会更改,从而img.complete仅在事件发生时才变为true火灾)。
gsnedders

72

Image.onload()通常会起作用。

要使用它,您需要确保在设置src属性之前绑定事件处理程序。

相关链接:

用法示例:

    window.onload = function () {

        var logo = document.getElementById('sologo');

        logo.onload = function () {
            alert ("The image has loaded!");		
        };

        setTimeout(function(){
            logo.src = 'https://edmullen.net/test/rc.jpg';         
        }, 5000);
    };
 <html>
    <head>
    <title>Image onload()</title>
    </head>
    <body>

    <img src="#" alt="This image is going to load" id="sologo"/>

    <script type="text/javascript">

    </script>
    </body>
    </html>


26
仅供参考:根据W3C规范,对于IMG元素,onload不是有效事件。显然,浏览器确实支持它。但是,如果您在乎规格要求,并且不能百分百确定要定位的所有浏览器都支持它,则可能需要重新考虑或至少记住这一点。
詹森·邦廷

3
为什么等待5秒钟来设置信号源似乎是个坏主意?
2014年

8
@quemeful这就是为什么它被称为“示例”的原因。
Diego Jancic 2015年

3
@JasonBunting您在看什么,使您认为该load活动无效?html.spec.whatwg.org/multipage/webappapis.html#handler-onloadonload 事件处理程序的定义。
gsnedders

4
@gsnedders-您意识到,我想,当我写此评论时,我指的是现存的标准,而不是您所指的标准,即新的4.5年。那时您可能会问,也许我可以指出这一点。这就是网络的本质吧?事情变得陈旧或移动或将被修改,等等
贾森鹀

20

您可以使用Javascript图像类的.complete属性。

我有一个应用程序,其中将多个Image对象存储在一个数组中,该对象将动态添加到屏幕上,并且在它们加载时,我将更新内容写入页面上的另一个div。这是一个代码片段:

var gAllImages = [];

function makeThumbDivs(thumbnailsBegin, thumbnailsEnd)
{
    gAllImages = [];

    for (var i = thumbnailsBegin; i < thumbnailsEnd; i++) 
    {
        var theImage = new Image();
        theImage.src = "thumbs/" + getFilename(globals.gAllPageGUIDs[i]);
        gAllImages.push(theImage);

        setTimeout('checkForAllImagesLoaded()', 5);
        window.status="Creating thumbnail "+(i+1)+" of " + thumbnailsEnd;

        // make a new div containing that image
        makeASingleThumbDiv(globals.gAllPageGUIDs[i]);
    }
}

function checkForAllImagesLoaded()
{
    for (var i = 0; i < gAllImages.length; i++) {
        if (!gAllImages[i].complete) {
            var percentage = i * 100.0 / (gAllImages.length);
            percentage = percentage.toFixed(0).toString() + ' %';

            userMessagesController.setMessage("loading... " + percentage);
            setTimeout('checkForAllImagesLoaded()', 20);
            return;
        }
    }

    userMessagesController.setMessage(globals.defaultTitle);
}

我以前在工作中使用过类似的代码。这在所有浏览器中都很好用。
加布里埃尔·赫尔利

2
检查完成的问题是,从IE9开始,将在加载所有图像之前触发OnLoad事件,并且现在很难为检查功能找到触发器。
Gene Vincent


8

jQuery的生命太短了。

function waitForImageToLoad(imageElement){
  return new Promise(resolve=>{imageElement.onload = resolve})
}

var myImage = document.getElementById('myImage');
var newImageSrc = "https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620"

myImage.src = newImageSrc;
waitForImageToLoad(myImage).then(()=>{
  // Image have loaded.
  console.log('Loaded lol')
});
<img id="myImage" src="">


1
这是一个很好的答案,但我认为您甚至不需要那么多代码。通过src与JS一起添加,只会使它看起来令人困惑。
布兰登·贝内菲尔德'18

1
时间是编程中的巨大限制。根据我的经验,编写可读的(很长时间)代码会带来巨大的时间收益。
伊丹·贝克

为什么将src存储到新变量中以便仅在下一行使用它?如果简洁是您的目标,那是一种反模式。myImage.src = https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620绝招。
乔西亚

3

这是等效的jQuery:

var $img = $('img');

if ($img.length > 0 && !$img.get(0).complete) {
   $img.on('load', triggerAction);
}

function triggerAction() {
   alert('img has been loaded');
}

1

提出问题时不适合2008年使用,但最近这些对我来说很有效:

async function newImageSrc(src) {
  // Get a reference to the image in whatever way suits.
  let image = document.getElementById('image-id');

  // Update the source.
  img.src = src;

  // Wait for it to load.
  await new Promise((resolve) => { image.onload = resolve; });

  // Done!
  console.log('image loaded! do something...');
}

0

这些函数将解决问题,您需要实现该DrawThumbnails函数并具有一个全局变量来存储图像。我喜欢让它与具有ThumbnailImageArray作为成员变量的类对象一起使用,但是很费劲!

称为 addThumbnailImages(10);

var ThumbnailImageArray = [];

function addThumbnailImages(MaxNumberOfImages)
{
    var imgs = [];

    for (var i=1; i<MaxNumberOfImages; i++)
    {
        imgs.push(i+".jpeg");
    }

    preloadimages(imgs).done(function (images){
            var c=0;

            for(var i=0; i<images.length; i++)
            {
                if(images[i].width >0) 
                {
                    if(c != i)
                        images[c] = images[i];
                    c++;
                }
            }

            images.length = c;

            DrawThumbnails();
        });
}



function preloadimages(arr)
{
    var loadedimages=0
    var postaction=function(){}
    var arr=(typeof arr!="object")? [arr] : arr

    function imageloadpost()
    {
        loadedimages++;
        if (loadedimages==arr.length)
        {
            postaction(ThumbnailImageArray); //call postaction and pass in newimages array as parameter
        }
    };

    for (var i=0; i<arr.length; i++)
    {
        ThumbnailImageArray[i]=new Image();
        ThumbnailImageArray[i].src=arr[i];
        ThumbnailImageArray[i].onload=function(){ imageloadpost();};
        ThumbnailImageArray[i].onerror=function(){ imageloadpost();};
    }
    //return blank object with done() method    
    //remember user defined callback functions to be called when images load
    return  { done:function(f){ postaction=f || postaction } };
}

11
此代码大部分与您的整个addThumbnailImages功能无关。将其粘贴到相关代码,然后删除-1。
贾斯汀·摩根

0

如果目标是在浏览器渲染图像后为img设置样式,则应该:

const img = new Image();
img.src = 'path/to/img.jpg';

img.decode().then(() => {
/* set styles */
/* add img to DOM */ 
});

因为浏览器首先是loads the compressed version of image,然后是decodes it,最后paints才是。因为没有事件,因此paint您应该在浏览器具有decodedimg标签之后运行逻辑。


-2

如果您使用的是React.js,则可以执行以下操作:

render() {

// ...

<img 
onLoad={() => this.onImgLoad({ item })}
onError={() => this.onImgLoad({ item })}

src={item.src} key={item.key}
ref={item.key} />

// ...}

哪里:

  • -onLoad(...)现在将使用类似这样的名称进行调用:{src:“ https://......png ”,key:“ 1”}您可以将其用作“ key”以了解哪些图像已正确加载,哪些未正确加载。
  • -onError(...)相同,但有错误。
  • -对象“ item”是这样的{key:“ ..”,src:“ ..”}},您可以使用它存储图像的URL和密钥,以便在图像列表中使用。

  • By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
    Licensed under cc by-sa 3.0 with attribution required.