วิธีสร้างการเรียกกลับ JavaScript เพื่อให้ทราบเมื่อโหลดรูปภาพ


145

ฉันต้องการทราบว่าเมื่อภาพโหลดเสร็จแล้ว มีวิธีการโทรกลับหรือไม่?

ถ้าไม่มีวิธีทำเลยหรือไม่?


2
github.com/desandro/imagesloaded - Folks ตรวจสอบแพ็คเกจนี้
mangatinanda

คำตอบ:


164

.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โทร?
Thomas Ahle

@ThomasAhle ฉันไม่ใช่ผู้เชี่ยวชาญ แต่ดูเหมือนจะเป็นไปได้ มาดูกันว่าใครมีวิธีแก้
Ciro Santilli 郝海东冠状病六四事件

ฉันเดาว่ามันน่าจะเป็นปัญหาสำหรับโค้ดคู่ขนานซึ่งจาวาสคริปต์ส่วนใหญ่อาจไม่ใช่ ..
Thomas Ahle

4
@ThomasAhle ไม่ได้เนื่องจากเบราว์เซอร์จะเริ่มการทำงานของเหตุการณ์โหลดเมื่อมีการหมุนคิวเหตุการณ์ ที่กล่าวว่าloadผู้ฟังเหตุการณ์จะต้องอยู่ในelseประโยคซึ่งimg.completeจะกลายเป็นจริงได้ก่อนที่loadเหตุการณ์จะเริ่มทำงานดังนั้นหากคุณไม่สามารถloadedโทรได้ถึงสองครั้ง (โปรดทราบว่าสิ่งนี้มีแนวโน้มที่จะเปลี่ยนไปซึ่งimg.completeจะกลายเป็นจริงก็ต่อเมื่อเหตุการณ์นั้น ไฟ)
gsnedders

74

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>


27
FYI: ตามข้อมูลจำเพาะของ W3C onload ไม่ใช่เหตุการณ์ที่ถูกต้องสำหรับองค์ประกอบ IMG เห็นได้ชัดว่าเบราว์เซอร์รองรับ แต่ถ้าคุณสนใจเกี่ยวกับข้อมูลจำเพาะและไม่แน่ใจ 100% ว่าเบราว์เซอร์ทั้งหมดที่คุณต้องการกำหนดเป้าหมายรองรับสิ่งนี้คุณอาจต้องคิดใหม่หรืออย่างน้อยก็ควรจำไว้
Jason Bunting

3
ทำไมการรอ 5 วินาทีเพื่อตั้งค่าแหล่งที่มาจึงดูเหมือนเป็นความคิดที่ไม่ดี
ไร้สาระ

9
@quemeful นั่นจึงเรียกว่า "ตัวอย่าง"
Diego Jancic

3
@JasonBunting คุณมองอะไรที่ทำให้คุณคิดว่าloadเหตุการณ์ไม่ถูกต้อง? html.spec.whatwg.org/multipage/webappapis.html#handler-onloadคือคำจำกัดความของonload ตัวจัดการเหตุการณ์
gsnedders

4
@gsnedders - คุณรู้ไหมฉันคิดว่าเมื่อฉันเขียนความคิดเห็นนั้นฉันกำลังอ้างถึงมาตรฐานที่ยังหลงเหลืออยู่ไม่ใช่มาตรฐานที่คุณชี้ไปซึ่งใหม่กว่า 4.5 ปี ที่คุณเคยถามกลับไปตอนนั้นฉันอาจจะชี้ไปที่มันได้ นั่นเป็นลักษณะของเว็บใช่ไหม? สิ่งต่างๆเริ่มเก่าหรือถูกเคลื่อนย้ายหรือถูกปรับเปลี่ยน ฯลฯ
Jason Bunting

20

คุณสามารถใช้คุณสมบัติ. complete ของคลาสรูปภาพ Javascript

ฉันมีแอปพลิเคชันที่ฉันเก็บออบเจ็กต์รูปภาพจำนวนหนึ่งไว้ในอาร์เรย์ซึ่งจะถูกเพิ่มลงในหน้าจอแบบไดนามิกและในขณะที่กำลังโหลดฉันจะเขียนอัปเดตไปยัง 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);
}

ฉันเคยใช้รหัสที่คล้ายกันในงานของฉันมาก่อน ซึ่งใช้ได้ดีในทุกเบราว์เซอร์
Gabriel Hurley

2
ปัญหาในการตรวจสอบความสมบูรณ์คือการเริ่มต้นด้วย IE9 เหตุการณ์ OnLoad จะเริ่มทำงานก่อนที่รูปภาพทั้งหมดจะถูกโหลดและตอนนี้หาทริกเกอร์สำหรับฟังก์ชันการตรวจสอบได้ยาก
Gene Vincent

11

คุณสามารถใช้ load () - เหตุการณ์ใน jQuery ได้ แต่จะไม่เริ่มทำงานเสมอไปหากรูปภาพถูกโหลดจากแคชของเบราว์เซอร์ ปลั๊กอินhttps://github.com/peol/jquery.imgloaded/raw/master/ahpi.imgload.jsนี้สามารถใช้เพื่อแก้ไขปัญหานั้นได้


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
Brandon Benefield

1
เวลาเป็นข้อ จำกัด อย่างมากในการเขียนโปรแกรม จากประสบการณ์ของฉันการเขียนโค้ดที่อ่านได้ (ในขณะที่ใช้เวลานาน) ให้ประโยชน์อย่างมาก
Idan Beker

เหตุใดคุณจึงเก็บ src ไว้ในตัวแปรใหม่เพื่อใช้ในบรรทัดถัดไปเท่านั้น หากความกะทัดรัดเป็นเป้าหมายของคุณนั่นคือการต่อต้านรูปแบบ myImage.src = https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620เคล็ดลับไม่
Josiah

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

หากเป้าหมายคือการจัดรูปแบบ 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


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
Justin Morgan

-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 ", คีย์: "1"} คุณสามารถใช้สิ่งนี้เป็น "คีย์" เพื่อทราบว่าภาพใด โหลดอย่างถูกต้องและไม่
  • - onError (... ) เหมือนกัน แต่มีข้อผิดพลาด
  • - ออบเจ็กต์ "item" คือ {คีย์: ".. ", src: ".. "} นี้คุณสามารถใช้เก็บ URL และคีย์ของรูปภาพเพื่อใช้ในรายการรูปภาพได้

  • โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
    Licensed under cc by-sa 3.0 with attribution required.