如何创建 JavaScript 回调以了解图像何时加载?

Posted

技术标签:

【中文标题】如何创建 JavaScript 回调以了解图像何时加载?【英文标题】:How to create a JavaScript callback for knowing when an image is loaded? 【发布时间】:2010-09-21 18:10:58 【问题描述】:

我想知道图像何时完成加载。有没有办法通过回调来做到这一点?

如果没有,有没有办法做到这一点?

【问题讨论】:

github.com/desandro/imagesloaded - 伙计们,看看这个包。 【参考方案1】:

.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/

【讨论】:

如果图像在img.complete 调用和addEventListener 调用之间完成,这会出错吗? @ThomasAhle 我不是专家,但这似乎是可能的。让我们看看是否有人有解决方案。 我猜这只是并行代码的问题,而大多数 javascript 可能不是...... @ThomasAhle 不能,因为浏览器只会在事件队列旋转时触发 load 事件。也就是说,load 事件侦听器 必须else 子句中,因为 img.complete 可以在 load 事件被触发之前变为真,因此如果不是,你可能会两次调用loaded(注意这很可能发生变化,img.complete 仅在事件触发时才变为真)。【参考方案2】:

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

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

相关链接:

Mozilla on Image.onload()

示例用法:

    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="#"  id="sologo"/>

    <script type="text/javascript">

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

【讨论】:

仅供参考:根据 W3C 规范,onload 不是 IMG 元素的有效事件。显然浏览器确实支持它,但如果你关心规范并且不能 100% 确定你想要定位的所有浏览器都支持它,你可能需要重新考虑它或至少牢记它。 为什么等待 5 秒来设置源似乎是个坏主意? @quemeful 这就是为什么它被称为“一个例子”。 @JasonBunting 你在看什么让你认为load 事件无效? html.spec.whatwg.org/multipage/webappapis.html#handler-onload 是onload 事件处理程序的定义。 @gsnedders - 你意识到,我假设,当我写那条评论时,我指的是现存的标准,而不是你指出的那个,它比 4.5 年新。如果你当时问过,我可能会指出它。这就是网络的本质,对吧?东西变旧或被移动或被修改等。【参考方案3】:

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

我有一个应用程序,我在一个数组中存储了许多 Image 对象,这些对象将被动态添加到屏幕上,并且当它们加载时,我将更新写入页面上的另一个 div。这是一个代码sn-p:

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);

【讨论】:

我以前在工作中使用过类似的代码。这适用于所有浏览器。 检查完成的问题是,从 IE9 开始,OnLoad 事件在所有图像加载之前触发,现在很难找到检查功能的触发器。【参考方案4】:

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')
);
&lt;img id="myImage" src=""&gt;

【讨论】:

这是一个很好的答案,但我认为您甚至不需要那么多代码。通过在 JS 中添加 src 只是让它看起来很混乱。 时间是编程的一个巨大限制。根据我的经验,编写可读(有时很长)的代码会带来巨大的时间收益。 为什么要将 src 存储到一个新变量中,只是为了在下一行使用它?如果简洁是您的目标,那就是反模式。 myImage.src = https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620 成功了。【参考方案5】:

您可以在 jQuery 中使用 load() 事件,但如果图像是从浏览器缓存中加载的,它不会总是触发。这个插件https://github.com/peol/jquery.imgloaded/raw/master/ahpi.imgload.js 可以用来解决这个问题。

【讨论】:

【参考方案6】:

这是 jQuery 等价物:

var $img = $('img');

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


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

【讨论】:

【参考方案7】:

当这个问题被问到时,不适合 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...');

【讨论】:

【参考方案8】:

如果目标是在浏览器渲染图像后设置 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 没有事件,您应该在浏览器具有decoded img 标签后运行您的逻辑。

【讨论】:

【参考方案9】:

这些函数将解决问题,您需要实现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  ;

【讨论】:

这段代码大部分是不相关的,包括你的整个addThumbnailImages函数。将其缩减为相关代码,我将删除 -1。【参考方案10】:

如果你使用 React.js,你可以这样做:

render() 

// ...

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

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

// ...

在哪里:

- onLoad (...) 现在将调用如下内容: 源:“https://......png”,键:“1” 您可以将其用作“关键”来了解哪些图像已正确加载,哪些未正确加载。 - onError(...) 它是相同的,但对于错误。 - 对象 "item" 是这样的 key:"..", src:".." 您可以使用存储图像的 URL 和密钥,以便在图像列表中使用。

【讨论】:

以上是关于如何创建 JavaScript 回调以了解图像何时加载?的主要内容,如果未能解决你的问题,请参考以下文章

在 JavaScript 中播放一段声音时如何获取回调?

JavaScript 何时同步?

jQuery.ajax() 成功/失败回调何时调用?

AngularJS中ng-src的图像加载事件

你如何检测 CSS 动画何时以 JavaScript 开始和结束?

Javascript 创建文件上传字段何时失败?