2013-06-04 7 views
13

Szukałem wielu odpowiedzi na JavaScript, ale nie znalazłem takiego, który naprawdę odpowie na mój problem. Próbuję załadować obraz, pobrać dane piksela, przeprowadzić analizę, a następnie załadować kolejny obraz, aby powtórzyć proces.JavaScript czeka, aż obraz zostanie w pełni załadowany przed kontynuowaniem skryptu

Mój problem polega na tym, że nie mogę wstępnie wczytać wszystkich obrazów, ponieważ ten skrypt musi być w stanie pracować na dużych ilościach obrazów, a wstępne ładowanie może być zbyt dużym zasobem. Tak więc utknąłem próbując załadować nowy obraz za każdym razem, gdy przechodzę przez pętlę, ale utknąłem z powodu wyścigu pomiędzy ładowaniem obrazu a scenariuszem rysującym go w kontekście płótna. Przynajmniej jestem całkiem pewien, że tak właśnie się dzieje, ponieważ skrypt będzie działał dobrze z wyeksponowanymi obrazami (na przykład, jeśli odświeżam po wczytaniu strony wcześniej).

Jak widzisz, kilka linii kodu zostało zakomentowanych, ponieważ jestem niesamowicie nowy w JavaScript i nie działały tak, jak myślałem, ale nie chciałem o nich zapomnieć, jeśli potrzebował później funkcjonalności.

Jest to fragment kodu, który moim zdaniem jest powodującego problemu:

EDIT: Więc mam moją funkcję do pracy po wykonaniu sugestii

function myFunction(imageURLarray) { 
    var canvas = document.getElementById('imagecanvas'); 
    console.log("Canvas Grabbed"); 

    if (!canvas || !canvas.getContext) { 
    return; 
    } 

    var context = canvas.getContext('2d'); 

    if (!context || !context.putImageData) { 
    return; 
    } 

    window.loadedImageCount = 0; 
    loadImages(context, canvas.width, canvas.height, imageURLarray, 0); 
} 

function loadImages(context, width, height, imageURLarray, currentIndex) { 
    if (imageURLarray.length == 0 || imageURLarray.length == currentIndex) { 
    return false; 
    } 
    if (typeof currentIndex == 'undefined') { 
    currentIndex = 0; 
    } 

    var currentimage = new Image(); 
    currentimage.src = imageURLarray[currentIndex]; 

    var tempindex = currentIndex; 
    currentimage.onload = function(e) { 

    // Function code here 

    window.loadedImageCount++; 

    if (loadedImageCount == imageURLarray.length) { 

     // Function that happens after all images are loaded here 
    } 
    } 
    currentIndex++; 
    loadImages(context, width, height, imageURLarray, currentIndex); 
    return; 
} 
+0

To pytanie nadal pobiera widoki 4 lata później, więc pomyślałem, że wspomnę, że jeśli masz dużo obrazów, możesz chcieć wywołać rekursywne 'loadImages' z' setTimeout (..., 0) 'aby stos wywołań nie przepełnia się. – Braains

Odpowiedz

13

Może to pomoże:

currentimage.onload = function(e){ 
    // code, run after image load 
} 

Jeśli jest to konieczne, aby czekać na zdjęcie, aby załadować poniższy kod wczytuje następny obraz (currentIndex jest zmienna „img”):

var loadImages = function(imageURLarray, currentIndex){ 
    if (imageURLarray.length == 0 || imageURLarray.length == currentIndex) return false; 
    if (typeof currentIndex == 'undefined'){ 
     currentIndex = 0; 
    } 
    // your top code 
    currentimage.onload = function(e){ 
     // code, run after image load 
     loadImages(imageURLArray, currentIndex++); 
    } 
} 

Zamiast pętli "for", wykorzystać na przykład tej funkcji:

loadImages(imageURLarray); 
+2

Patrzyłem na to, ale rozumiem, że reszta skryptu będzie działała, dopóki obraz się nie załaduje, a funkcja zostanie uruchomiona, więc będę miał ten sam stan wyścigu. – Braains

+0

@Brainy, jeśli poprawnie zaimplementowano, to nie. Jeśli masz inny kod, pokaż go – maximkou

+1

onload nie będzie czekać na załadowanie kolejnych zdjęć –

0

Może spróbuj tego:

http://jsfiddle.net/jnt9f/

Ustawianie obsługi onload przed ustawieniem img src uczyni pewność, że zdarzenie onload zostanie uruchomione, nawet obraz zostanie zbuforowany

var $imgs = $(),i=0; 
for (var img = 0; img < imageURLarray.length; img++) { 
    $imgs = $imgs.add('<img/>'); 
} 

var fctn = (function fctn(i){ 
    $imgs.eq(i).on('load',function(){ 
     //do some stuff 
     //... 
     fctn(++i); 
    }).attr('src',imageURLarray[i]);  
})(0); 
+0

Czy mógłbyś wyjaśnić trochę, co dzieje się w twoim przykładowym kodzie? Nie jestem tak zaznajomiony z JQuery, jak powinienem. – Braains

+0

Pozwoli to uniknąć jakiegokolwiek wyścigu. Rozpocznie się ładowanie następnego obrazu tylko wtedy, gdy poprzedni był w pełni załadowany. Zobacz jsfiddle w zaktualizowanej odpowiedzi –

+3

@downvoter, prosimy o komentarz na temat downvote ... –

0

Właściwie ... wiele deweloperów wskazują tutaj, aby wykryć, kiedy zdjęcia są wykonywane po załadowaniu zdarzenia jQuery ..

https://github.com/desandro/imagesloaded

Jeśli można ustalić, gdy zdarzenie wyzwala swoje obrazy do załadowania (dla przykład, dodając identyfikator lub klasę na stronie tuż przed rozpoczęciem ładowania obrazów), powinieneś być w stanie połączyć to z tą wtyczką na github.

Powodzenia!

+0

Próbowałem tego, ale nie ładuję tylko jednego obrazu, ładuję obraz za każdym razem w pętli. Wszystko to dzieje się po załadowaniu strony. – Braains

+0

ok, trzymaj się, myślę, że znalazłem coś. edytowanie mojej odpowiedzi teraz ... – blackhawk

+0

Problem z preinstalacją polega na tym, że mam do czynienia z potencjalnie dużą liczbą obrazów. – Braains

Powiązane problemy