Як створити зворотний дзвінок JavaScript, щоб дізнатися, коли завантажується зображення?


136

Я хочу знати, коли зображення закінчується завантаженням. Чи є спосіб зробити це з зворотним дзвінком?

Якщо ні, чи є спосіб це зробити взагалі?


2
github.com/desandro/imagesloaded - Люди, перевірте цей пакет.
mangatinanda

Відповіді:


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.
Thomas Ahle

4
@ThomasAhle Це не може, оскільки браузер запустить подію завантаження лише тоді, коли черга подій закручена. Тим не менше , loadслухач події повинні бути в elseреченні, так як img.completeможе стати реальністю до того , як loadподія викликається, отже , якби не ви могли б потенційно бути loadedвикликаний двічі (зверніть увагу , що це відносно , ймовірно, зміниться таким чином, що img.completeтільки стає справжнім , коли подія пожежі).
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
FYI: Відповідно до специфікації W3C, завантаження не є дійсною подією для елементів IMG. Очевидно, що браузери це підтримують, але якщо ви піклуєтесь про технічну характеристику та не впевнені на 100%, що всі браузери ви хочете націлити цю підтримку, ви можете переосмислити її або хоча б пам’ятати про це.
Джейсон Бантінг

3
чому очікування 5 секунд для встановлення джерела здається поганою ідеєю?
пам’ятний

8
@quemeful тому його називають "прикладом".
Дієго Янчич

3
@JasonBunting Що ви дивитесь, що змушує вас вважати, що loadподія недійсна? html.spec.whatwg.org/multipage/webappapis.html#handler-onload - це визначення onload обробника події.
gsnedders

4
@gsnedders - ви розумієте, я б припускав, що коли я писав цей коментар, я мав на увазі існуючий стандарт, а не той, на який ви вказали, який на 4,5 роки новіший. Що б ви тоді ще запитали, я, можливо, міг би вказати на це. Така природа Інтернету, правда? Речі старіють або переміщуються, або змінюються тощо.
Джейсон Бантінг

20

Ви можете використовувати властивість .complete класу зображень Javascript.

У мене є додаток, в якому я зберігаю ряд об’єктів Зображення в масиві, який буде динамічно додаватися на екран, і коли вони завантажуються, я записую оновлення до іншого діла на сторінці. Ось фрагмент коду:

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 запускаються перед завантаженням усіх зображень і важко знайти тригер для функції перевірки зараз.
Джин Вінсент


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
Це чудова відповідь, але я не думаю, що вам навіть не потрібен стільки код. Ви просто виглядаєте заплутаною, додаючи srcJS.
Брендон Бенефілд

1
Час - це величезне обмеження в програмуванні. З мого досвіду, написання читабельного (хоч і колись довгого) коду дає величезну перевагу в часі.
Ідан Бекер

Чому ви зберігаєте src у новій змінній лише для того, щоб споживати її в наступному рядку? Якщо стислість - ваша мета, це анти-модель. myImage.src = https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620робить трюк.
Йосія


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

Якщо мета - стилізувати зображення після того, як браузер надає зображення, вам слід:

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.


-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"} Ви можете використовувати це як "ключ", щоб знати, які зображення завантажується правильно, а яка ні.
  • - onError (...) це те саме, але для помилок.
  • - об'єкт "item" виглядає приблизно так {ключ: "..", src: ".."} ви можете використовувати для зберігання URL-адреси та ключа зображень для використання у списку зображень.

  • Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
    Licensed under cc by-sa 3.0 with attribution required.