如何在加载图像时运行 JavaScript 回调?

How can I run a JavaScript callback when an image is loaded?

提问人: 提问时间:11/11/2008 最后编辑:mikemaccana 更新时间:8/29/2023 访问量:264348

问:

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

如果没有,有没有办法做到?

JavaScript 图像 回调 加载

评论

2赞 mangatinanda 5/8/2018
github.com/desandro/imagesloaded - 伙计们,检查这个包。

答:

90赞 keparo 11/11/2008 #1

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>

评论

30赞 Jason Bunting 11/12/2008
仅供参考:根据 W3C 规范,onload 不是 IMG 元素的有效事件。显然,浏览器确实支持它,但如果你关心规范,并且不是 100% 确定你想要定位的所有浏览器都支持它,你可能需要重新考虑它,或者至少记住它。
5赞 quemeful 8/21/2014
为什么等待 5 秒来设置源似乎是一个坏主意?
10赞 Diego Jancic 11/6/2015
@quemeful这就是为什么它被称为“例子”。
3赞 gsnedders 4/8/2017
@JasonBunting 你在看什么,让你认为这个事件是无效的?html.spec.whatwg.org/multipage/webappapis.html#handler-onload 是事件处理程序的定义。loadonload
6赞 Jason Bunting 5/25/2017
@gsnedders - 你意识到,我假设,当我写那条评论时,我指的是现有的标准,而不是你所指的标准,它比现在新了 4.5 年。你当时问过,我也许可以指出来。这就是网络的本质,对吧?事物变旧或被移动或被修改等。
21赞 Jon DellOro 11/11/2008 #2

可以使用 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);
}

评论

0赞 Gabriel Hurley 8/9/2009
我以前在工作中使用过类似的代码。这在所有浏览器中都运行良好。
2赞 Gene Vincent 3/20/2013
检查完成的问题在于,从 IE9 开始,OnLoad 事件是在加载所有图像之前触发的,现在很难找到检查函数的触发器。
12赞 jimmystormig 2/6/2011 #3

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

0赞 dave 10/25/2012 #4

这些函数将解决问题,您需要实现该函数并有一个全局变量来存储图像。我喜欢让它与具有 as 成员变量的类对象一起使用,但我正在努力!DrawThumbnailsThumbnailImageArray

称为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 } };
}

评论

12赞 Justin Morgan 10/25/2012
这些代码的大部分都是无关紧要的,包括你的整个函数。将其缩减到相关代码,我将删除 -1。addThumbnailImages
222赞 Ciro Santilli OurBigBook.com 6/13/2014 #5

.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赞 Thomas Ahle 1/10/2017
如果图像在呼叫和呼叫之间完成,这会出错吗?img.completeaddEventListener
0赞 Ciro Santilli OurBigBook.com 1/11/2017
@ThomasAhle我不是专家,但这似乎是可能的。让我们看看是否有人有解决方案。
0赞 Thomas Ahle 1/11/2017
我想这只是并行代码的问题,而大多数 javascript 可能不是。
6赞 gsnedders 4/8/2017
@ThomasAhle 它不能,因为浏览器只会在事件队列旋转时触发加载事件。也就是说,事件侦听器必须位于子句中,因为在触发事件之前可以变为 true,因此如果不是,您可能会调用两次(请注意,这相对可能会发生变化,因此仅在事件触发时才变为 true)。loadelseimg.completeloadloadedimg.complete
0赞 12/4/2022
事件指定在哪里?似乎我没有在 MDN 上找到它?load
5赞 Alexander Drobyshevsky 3/22/2017 #6

下面是 jQuery 等效项:

var $img = $('img');

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

function triggerAction() {
   alert('img has been loaded');
}
19赞 Idan Beker 1/11/2018 #7

对于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="">

评论

4赞 Brandon Benefield 4/1/2018
这是一个很好的答案,但我认为你甚至不需要那么多代码。你只是通过添加 with JS 让它看起来令人困惑。src
2赞 Idan Beker 4/1/2018
时间是编程中的巨大制约因素。根据我的经验,编写可读的(虽然很长)代码会带来巨大的时间优势。
2赞 Josiah 12/11/2018
为什么要将 src 存储到一个新变量中,只是为了在下一行使用它?如果简洁是你的目标,那就是反模式。 做到了诀窍。myImage.src = https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620
-3赞 Mike 5/28/2018 #8

如果你使用的是 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“ } 您可以将其用作“关键”,以了解哪些图像已正确加载,哪些图像未正确加载。
  • - onError(...) 是相同的,但用于错误。
  • - 对象 “item” 是这样的 { key:“..”, src:“..”} 您可以使用来存储图像的 URL 和密钥,以便在图像列表中使用。

  • 5赞 Sajad 4/1/2020 #9

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

    const img = new Image();
    img.src = 'path/to/img.jpg';
    
    img.decode().then(() => {
    /* set styles */
    /* add img to DOM */ 
    });
    

    因为浏览器先,后,最后才是。由于没有事件,因此您应该在浏览器具有 img 标签后运行您的逻辑。loads the compressed version of imagedecodes itpaintspaintdecoded

    4赞 Hugh 6/4/2020 #10

    2008 年被问到这个问题时不适合,但现在这对我来说效果很好:

    async function newImageSrc(src) {
      // Get a reference to the image in whatever way suits.
      let image = document.getElementById('image-id');
    
      // Update the source.
      image.src = src;
    
      // Wait for it to load.
      await new Promise((resolve) => { image.onload = resolve; });
    
      // Done!
      console.log('image loaded! do something...');
    }
    

    评论

    0赞 Simbiat 7/8/2022
    我猜你的意思是image.src = src;
    0赞 Jesus is Lord 1/18/2023 #11

    这对我有用:

    // Usage
    let img = await image_on_load(parent_element_to_put_img, image_url);
    img.hidden = true;
    
    // Functions
    async function image_on_load(parent, url) {
        let img = element(parent, 'img');
        img.src = url;
        await new Promise((resolve, reject) => {
            element_on(img, 'load', () => {
                resolve();
            });
            element_on(img, 'error', () => {
                reject();
            });
        });
        return img;
    }
    function element(parent, tag_name, text = '') {
        let result = document.createElement(tag_name);
        element_child_append(parent, result);
        element_html_inner(result, text);
        return result;
    }
    function element_child_append(parent, result) {
        parent.appendChild(result);
    }
    function element_html_inner(result, text) {
        result.innerHTML = text;
    }
    function element_on(e, event, on_event) {
        e.addEventListener(event, async () => {
            await on_event();
        });
    }
    
    
    0赞 j.j. 8/7/2023 #12

    对不起,我忍不住简化 Ciro Santilli 在 2014 年的回答。
    这是来自真实世界网页的代码:

    if (img.complete)  loaded();
    else  img.onload = loaded();