Bagaimana cara membuat panggilan balik JavaScript untuk mengetahui kapan gambar dimuat?

145

Saya ingin tahu kapan gambar telah selesai dimuat. Apakah ada cara untuk melakukannya dengan panggilan balik?

Jika tidak, apakah ada cara untuk melakukannya?

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
2
github.com/desandro/imagesloaded - Teman -teman, periksa paket ini.
mangatinanda

Jawaban:

164

.complete + panggilan balik

Ini adalah metode yang sesuai standar tanpa ketergantungan tambahan, dan menunggu tidak lebih lama dari yang diperlukan:

var img = document.querySelector('img')

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

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

Sumber: http://www.html5rocks.com/en/tutorials/es6/promises/

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
4
Bisakah ini salah jika gambar selesai antara img.completepanggilan dan addEventListenerpanggilan?
Thomas Ahle
@ThomasAhle Saya bukan seorang ahli, tapi sepertinya itu mungkin. Mari kita lihat apakah ada yang punya solusi.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Saya kira itu hanya akan menjadi masalah untuk kode paralel, yang mungkin tidak sebagian besar javascript ..
Thomas Ahle
4
@ThomasAhle Tidak bisa, karena browser hanya akan mengaktifkan peristiwa pemuatan saat antrean peristiwa diputar. Yang mengatakan, loadpendengar acara harus berada dalam elseklausa, seperti img.completedapat menjadi benar sebelum loadacara dipecat, maka jika tidak Anda bisa berpotensi telah loadeddisebut dua kali (catatan ini relatif kemungkinan akan berubah sehingga img.completehanya menjadi benar ketika acara kebakaran).
gsnedders
74

Image.onload () akan sering berfungsi.

Untuk menggunakannya, Anda harus memastikan untuk mengikat pengendali kejadian sebelum Anda menyetel atribut src.

Tautan yang berhubungan:

Contoh Penggunaan:

    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>

keparo
sumber
27
FYI: Menurut spesifikasi W3C, onload bukanlah peristiwa yang valid untuk elemen IMG. Jelas sekali browser mendukungnya, tetapi jika Anda peduli dengan spesifikasi dan tidak 100% yakin semua browser yang ingin Anda targetkan mendukung ini, Anda mungkin ingin memikirkannya kembali atau setidaknya mengingatnya.
Jason Bunting
3
mengapa menunggu 5 detik untuk menyetel sumbernya tampak seperti ide yang buruk?
Quemeful
9
@quemeful itu sebabnya disebut "contoh".
Diego Jancic
3
@JasonBunting Apa yang Anda lihat yang membuat Anda berpikir bahwa loadacara tersebut tidak valid? html.spec.whatwg.org/multipage/webappapis.html#handler-onload adalah definisi dari onload event handler.
gsnedders
4
@gsnedders - Anda menyadari, saya akan berasumsi, bahwa ketika saya menulis komentar itu, saya mengacu pada standar yang masih ada, bukan yang Anda tunjuk, yaitu 4,5 tahun lebih baru. Seandainya Anda bertanya saat itu, saya bisa menunjukkannya, mungkin. Seperti itulah sifat web, bukan? Hal-hal menjadi tua atau dipindahkan atau diubah, dll.
Jason Bunting
20

Anda dapat menggunakan properti .complete dari kelas gambar Javascript.

Saya memiliki aplikasi tempat saya menyimpan sejumlah objek Gambar dalam sebuah array, yang akan ditambahkan secara dinamis ke layar, dan saat dimuat, saya menulis pembaruan ke div lain di halaman. Berikut cuplikan kodenya:

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);
}
Jon DellOro
sumber
Saya telah menggunakan kode serupa dalam pekerjaan saya sebelumnya. Ini berfungsi dengan baik di semua browser.
Gabriel Hurley
2
Masalah dengan pemeriksaan selesai adalah bahwa dimulai dengan IE9, peristiwa OnLoad dijalankan sebelum semua gambar dimuat dan sulit untuk menemukan pemicu untuk fungsi pemeriksaan sekarang.
Gene Vincent
8

Hidup ini terlalu singkat untuk 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="">

Idan Beker
sumber
1
Ini adalah jawaban yang bagus tetapi saya rasa Anda bahkan tidak membutuhkan banyak kode. Anda hanya membuatnya terlihat membingungkan dengan menambahkan srcwith JS.
Brandon Benefield
1
Waktu adalah kendala besar dalam pemrograman. Dari pengalaman saya, menulis kode yang dapat dibaca (sementara kadang-kadang panjang) memberikan manfaat waktu yang sangat besar.
Idan Beker
Mengapa Anda menyimpan src ke variabel baru hanya untuk dipakai di baris berikutnya? Jika keringkasan adalah tujuan Anda, itu adalah anti-pola. myImage.src = https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620berhasil.
Yosia
3

Berikut ini setara dengan jQuery:

var $img = $('img');

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

function triggerAction() {
   alert('img has been loaded');
}
Alexander Drobyshevsky
sumber
1

Jika tujuannya adalah untuk memberi gaya pada img setelah browser merender gambar, Anda harus:

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

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

karena browser pertama loads the compressed version of image, lalu decodes it, akhirnya paints. karena tidak ada acara untuk paintAnda harus menjalankan logika Anda setelah browser memiliki decodedtag img.

Sajad
sumber
1

Tidak sesuai untuk tahun 2008 ketika pertanyaan itu diajukan, tetapi sekarang ini bekerja dengan baik untuk saya:

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...');
}
Hugh
sumber
0

fungsi-fungsi ini akan menyelesaikan masalah, Anda perlu mengimplementasikan DrawThumbnailsfungsi tersebut dan memiliki variabel global untuk menyimpan gambar. Saya suka membuat ini bekerja dengan objek kelas yang memiliki ThumbnailImageArrayvariabel sebagai anggota, tapi saya kesulitan!

dipanggil sebagai di 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 } };
}
dave
sumber
11
Sebagian besar kode ini tidak relevan, termasuk seluruh addThumbnailImagesfungsi Anda. Pare ke kode yang relevan dan saya akan menghapus -1.
Justin Morgan
-2

Jika Anda menggunakan React.js, Anda dapat melakukan ini:

render() {

// ...

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

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

// ...}

Dimana:

  • - onLoad (...) sekarang akan dipanggil dengan sesuatu seperti ini: {src: " https: //......png ", key: "1"} Anda dapat menggunakan ini sebagai "key" untuk mengetahui gambar yang mana dimuat dengan benar dan mana yang tidak.
  • - onError (...) sama tetapi untuk kesalahan.
  • - objek "item" adalah sesuatu seperti ini {key: "..", src: ".."} yang dapat Anda gunakan untuk menyimpan URL dan kunci gambar agar dapat digunakan dalam daftar gambar.

  • Mike
    sumber