[js] wczytanie obrazka

0

witam. zamieszczam fragment kodu który napisałem jakis czas temu, a teraz potrzebowalbym go przerobic tak aby obrazek, ktory tworze sobie dynamicznie, zostal zaladowany do pamieci, a dopiero potem byl ladnie, w calosci wyswietlony. troszke tez tu napsułem także kod poniżej nie dziala i nie moge sobie juz z nim poradzic.. zeby doprowadzic do zamierzonego efektu probowalem tez uzyc "new Image()" ale pewnie znow cos zle pisalem..


var adresy = [ '1.jpg', '2.jpg' ];
var wczytanezdjecia = 0;
var zdjecie = [];
.
.

function blabla() {
.
.
  while ( wczytanezdjecia < adresy.length ) { 

    zdjecie[wczytanezdjecia] = $(document.createElement("img"));
    zdjecie[wczytanezdjecia].attr({ src: adresy[wczytanezdjecia]});
    zdjecie[wczytanezdjecia].onload = function() {
    zdjecie[wczytanezdjecia].attr({ rel: wczytanezdjecia }).addClass("fota").appendTo($(strona[str]));
    zdjecie[wczytanezdjecia].click(prezentuj);
											
    };

  wczytanezdjecia++; 

  }

}
0

Nie napisałeś, z jakiej biblioteki korzystasz. Skąd mamy wiedzieć, co zwraca funkcja $?

Domyślam się, że korzystasz z jQuery. Skoro tak, to nie używaj zwykłej, przeglądarkowej obsługi zdarzeń, czyli onload. Zamiast tego użyj funkcji load, zapewnianej przez jQuery (działającej podobnie jak click). Jak czegoś nie wiesz, to poszukaj funkcji load na api.jquery.com.

Poza tym popraw formatowanie (wcięcia!). Nie widać, co należy do ciała funkcji anonimowej podstawianej do onload, a co nie. Staranność i drobiazgowość we wcięciach jest ważna.

No i masz klasyczny błąd wynikający z braku zrozumienia domknięć. Podstawowa zasada jest taka, by nie używać ich w pętli, gdy nie wiesz, co robisz ;). Gdy wywoła się funkcja obsługująca zdarzenie load dla dowolnego obrazka, to zmienna wczytanezdjecia będzie zawsze miała wartość równą adresy.length (!).

Spróbuj wydzielić funkcję tworzącą obiekt jQuery i dodającą te wszystkie bajery, które masz w ciele pętli. Zrób coś takiego:

function stworz_obiekt_zdjecia(nr) {
  var $zdjecie = $(document.createElement('img'));
  $zdjecie.attr({ src: adresy[nr] });
  $zdjecie.load(function() { // zamiast onload
    $zdjecie.attr(...);
    $zdjecie.click(prezentuj);
  });
  return $zdjecie;
}

Tutaj założyłem, że funkcja zależy tylko od zmiennej wczytanezdjecia. Zmienna ta zostanie przekazana do funkcji w parametrze nr. Jeśli zależy ona od jeszcze innych zmiennych (np. strona, str -- z fragmentu Twojego kodu nie wiadomo, skąd one się biorą), to możesz dodać kolejne parametry. Ale jeśli będzie ich więcej niż 3, to coś jest nie tak.

Zwracaną zmienną nazwałem $zdjecie, bo taka jest konwencja, by nazwy obiektów jQuery rozpoczynać od $. To tylko taka umowa programistów, w rzeczywistości znaczek $ niczego specjalnego dla JavaScriptu nie oznacza.

Funkcję stworz_obiekt_zdjecia wywołuj po prostu zamiast ciała pętli:

while ( wczytanezdjecia < adresy.length  ) {
  zdjecie[wczytanezdjecia] = stworz_obiekt_zdjecia(wczytanezdjecia);
  wczytanezdjecia++;
}

Zauważ proszę, że pozwoliło to uniknąć powtórzeń zdjecie[indeks], których JavaScript nie lubi (są wolne!).

Szczerze mówiąc nie podoba mi się nazwa zmiennej 'wczytanezdjecia'. W momencie gdy pętla jest wywoływana, te zdjęcia nie są jeszcze wczytane. IMO prawdopodobnie możesz wywalić tę zmienną globalną i w funkcji blabla() stworzyć lokalną zmienną iteracyjną o nazwie choćby "i" (w małym, lokalnym zakresie takie nazwy są OK). Albo "nr_zdjecia", jak chcesz być bardziej... treściwy. Pętlę while możesz wtedy zmienić na for.

function blabla() {
  ..
  for (var nr_zdjecia  = 0; nr_zdjecia < adresy.length; nr_zdjecia++) {
    zdjecie.push(stworz_obiekt_zdjecia(nr_zdjecia)); // to samo co zdjecie[nr_zdjecia] = stworz_obiekt_zdjecia(nr_zdjecia)
  }
  ..
}

I kod robi się bardziej elegancki :).

Aha, tablicę zdjęć nazwij raczej "zdjecia" a nie "zdjecie". Tablica reprezentuje przecież wiele obiektów, niech ma liczbę mnogą. Tylko wprowadzaj te wszystkie zmiany po kolei, a nie naraz!

0

No proszę taka pora, a taki dobry refaktoring kodu na dobranoc przeczytałem (:

Aha, tablicę zdjęć nazwij raczej "zdjecia" a nie "zdjecie". Tablica reprezentuje przecież wiele obiektów, niech ma liczbę mnogą. Tylko wprowadzaj te wszystkie zmiany po kolei, a nie naraz!

I to dlatego czasem humaniści w programowaniu mają łatwiej! (:

0

ekstra :) o takie cos mi chodzilo.. wygląda na to że po ukończeniu obecnego projektu będę musiał się zająć domknięciami bo bo ten problem pojawia się u mnie coraz częściej :P

PS. obecne nazwy zmiennych zostały użyte troche z konieczności bo 'intuicyjne' nazwy są już pozajmowane dla innych tablic.. aczkolwiek i tak będę musiał jakoś to uprzatnac :)

0

@DewREW:
Poczytaj, poczytaj o tych domknięciach. To mechanizm bardzo ważny i często używany (choćby nieświadomie). Mamy z nimi do czynienia zawsze, gdy funkcja wewnętrzna, zagnieżdżona w funkcji zewnętrznej, korzysta ze zmiennych funkcji zewnętrznej.

Prosty sposób na ominięcie problemów to nie stosowanie domknięć w pętli. A gdy je stosujesz, to wydziel funkcję wykonującą jedną iterację pętli -- tak, jak ja to zrobiłem (funkcja stworz_obiekt_zdjecia). To jest bezpieczne, a poza tym polepsza czytelność.

Co do nazewnictwa to pomóc by Ci mogła obiektowość :). Generalnie trzeba unikać zmiennych globalnych. M.in. dlatego, że gdy ich przybywa, pojawiają się konflikty nazw. Programowanie zorientowane obiektowo to rozwiązuje, grupując zmienne i funkcje w obiektach. Ja pracuję teraz nad sporym projektem w JS. Ma parę tysięcy linii i setki zmiennych. Nie mam absolutnie żadnych problemów z konfliktami nazw. Zmienną globalną mam jedną. Stanowi jakby przestrzeń nazw dla całej aplikacji. Przytłaczająca większość pozostałych zmiennych, jeśli nie wszystkie, to zmienne prywatne.

Trochę o domknięciach i programowaniu obiektowym masz w książce Douglasa Crockforda "JavaScript -- Mocne strony". Krótka, zwięzła, niedroga. Uczy dobrze języka JavaScript, choć nie dostarcza gotowych skryptów, które można wkleić na stronę. Ale widzę, że sam potrafisz już napisać większe kawałki kodu, więc nie jesteś z tych, co tylko dodają gotowce.

Wydaje mi się, że dobra może też być inna książka. Prawdopodobnie jest bardziej łopatologiczna i tłumaczy wszystko może bardziej rozwlekle, ale dając czas na własne przemyślenia (Crockford tłumaczy wszystko szybko, więc samemu trzeba sobie ten czas wydzielać). To "JavaScript. Programowanie obiektowe". Zaznaczam jednak, że NIE CZYTAŁEM tej książki. Prawdopodobnie jej nie kupię, bo niczego by mnie nie nauczyła. Jak ją kupię, to dlatego, by móc ją lepiej ocenić, ale póki co mam w kolejce kilka ważniejszych dla mnie książek.

Patrzyłem jednak w spis treści "Programowania obiektowego" oraz zerknąłem na fragmenty i muszę powiedzieć, że wygląda to dobrze. Opisane są ekstremalnie przydatne wzorce. Domknięcia też. Pułapka z domknięciem w pętli też.

Trudno mi ocenić, jak odbierze książkę Crockforda ktoś, kto nie ma dużego doświadczenia w językach formalnych, programowaniu funkcyjnym itd. Jak w książce Crockforda nie dotrze do Ciebie jakiś paragraf lub dwa, to albo go przeczytasz i przeanalizujesz raz jeszcze, albo ominie Cię coś bardzo ważnego. W książce "JavaScript. Programowanie obiektowe" tempo wydaje się o wiele spokojniejsze, a wciąż kosztuje tylko 50 zł, mając ponad 300 stron. Jak na książki informatyczne, cena wydaje się OK.

0

tak się składa że te ksiazke "javascript.programowanie obiektowe" mam w swoim zasiegu, tzn nie ma jakiegos problemu żebym ją np juz jutro sobie pożyczyl :) ale obecnie czasowo i tak nie byłbym wstanie się nia zajac, a niestety, programowanie wymaga troche wiecej uwagi :P
bswierczynski - zwracam się bezpośrednio do Ciebie ze wzgledu na to że poważnie podchodzisz do problemów które ktoś opisuje na forum i liczę że jeszcze raz mnie wspomożesz.. wiec.. napisałem od zera galerie. nie jest to jakies mega wystrzałowe, a kod jest pisany na chłopski rozum (co nie prezentuje sie jak mniemam zbyt dobrze..). ale problem jest następujący: w firefoxie i safari smiga jak burza, za to w IE i.. operze wisi i nic sie nie dzieje... po prostu nie wyświetlają obrazków, tak jakby w ogole pomijali 'load'. i na prawdę nie wiem jak to ugryźć, poswiecilem temu caly dzisiejszy dzien i nie posunalem się w żadną stronę. czyzby znów jakieś "nieświadome domknięcie" ? okroiłem kod na tyle żeby zaprezentować sam problem. proponowałbym zajrzeć do tej paczuszki (500kb)

1 użytkowników online, w tym zalogowanych: 0, gości: 1