[javascript] ImageCache

0

Witam, od jakiegos czasu szukam sposobu na ladowanie graficznych backgroundow zanim wyswietlona zostanie cala strona. znalalzlem w sieci cos takiego jak "ImageCache", z tym ze nie bardzo moge dojsc do tego jak to nalezy zastosowac, pomijam fakt, ze nie jestem tez ani biegly z JS ani z angielskiego, miedzy wierszami wyczytuje.. :P [url=http://alexrabarts.github.com/jquery-cacheimage]tutaj zamieszczam stronke [/url], do tego zalaczam kod zrodlowy ktory obecnie samodzielnei maltretuje. przy pomocy "hover" sprawdzam czy drugi obrazek faktycznie siedzi juz w pamieci ale niestety - zanim obrazki zostana zmienione nastepuje wczytanie tego ktory chcialbym aby juz siedzial w pamieci...
bardzo proszę o jakaś pomoc, ewentualnie przetlumaczenie na chlopski rozum skladni tej funkcji ImageCache, bo od 3 dni tkwie w miejscu pt "ladowanie grafiki do pamieci"..

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=ISO-8859-2">
<title>Dokument bez nazwy</title>

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="http://plugins.jquery.com/files/jquery.cacheimage.js.txt"></script>

<style type="text/css">
* { margin: 0 auto; padding: 0;}
#obraz { background-image:url(Obraz1.jpg); display: block; height: 800px; width: 600px;}
#obraz:hover {background-image:url(Obraz11.jpg);} </style>

<script type="text/javascript"> 
function dodajZdarzenie(odnosnik, zdarzenie, funkcja){
	if (odnosnik.addEventListener) {
		odnosnik.addEventListener(zdarzenie, funkcja, false); 
	}
	else { 
		odnosnik.attachEvent("on"+zdarzenie, funkcja); 
	}
}



	var obrazki = [
				   'obraz1.jpg',
				   'obraz11.jpg',
				   //'obraz2.jpg',
				   //'obraz3.jpg',
				  // 'obraz4.jpg',
				  // 'obraz5.jpg',
				  // 'obraz6.jpg',
				 //  'obraz7.jpg',
				 //  'obraz8.jpg',
				   ];

function Laduj () {
	for(x=0; x< obrazki.length; x++) {
		   $.cacheImage(obrazki[x])
	alert(obrazki[x])
	}
}

dodajZdarzenie(window, 'load', Laduj)
</script>

</head>

<body>
<div id="obraz"></div>
</body>
</html>
0

Z tego co widzę, to ImageCache jest takim rozszerzeniem prostej metody:

new Image().src = "adres_obrazka.jpg";

Kod wyżej tworzy obiekt klasy Image, któremu od razu przypisywana jest wartość src - link do obrazka. Przeglądarka od razu wczytuje obrazek.
Spróbuj zrobić tak:

var obrazki = [...];
for(var x=0; x< obrazki.length; x++) {
   var obrazek = new Image();
   obrazek.src = obrazki[x];
}

I to umieść w zdarzeniu DOMContentLoaded (wykonywane wcześniej niż OnLoad). Używasz, jQuery, więc będzie to tak:

$.ready(function() {
  for(...) { var obrazek ...  }
});
0

@DewREW:
Nie bardzo rozumiem w czym masz problem. Jeśli od razu chcesz zcache'ować obrazki, to nie musisz stosować żadnego onload. Nie musisz cache'ować obrazków pojedynczo. Gdy ścieżki do obrazków masz w tablicy obrazki, to wywołaj po prostu:

$.cacheImage(obrazki);

Tak naprawdę to jest spora szansa, że w ogóle nie musisz tego używać. Ja zamiast tego używam zwykle techniki zwanej sprite'ami CSS (ang. css sprites). Możesz o tym pogooglać.

Niestety, programista bez angielskiego jest jak bez ręki. Z tą różnicą, że może coś zrobić, by ten stan rzeczy zmienić. Istnieją doskonałe artykuły odnośnie sprite'ów CSS, ale po angielsku. Po polsku nie będę żadnego polecał, bo nie ręczę za twórców, których nie znam. Poza tym angol jest niezbędny do czytania dokumentacji.

Podobno każdy programista, by zachować jasność umysłu, powinien raz na jakiś czas opanować nowy język. Chodzi o język programowania, ale Tobie na pierwszy ogień polecam... angielski. Poważnie. Nie może być sytuacji, że nie rozumiesz dokumentacji i prosisz ludzi na forach, żeby Ci to wytłumaczyli. To kompletnie nie pasuje do profesjonalnego programisty.

0

to
$.cacheImage(obrazki);
w ogóle nie łapie. przy podmianie obrazkow i tak nastepuje przerwa i na pasku pisze "pobieranie pliku xyz". ale dzieki za szybką reakcję. do cache'owania wrócę rano bo teraz juz nie mam sily ale chyba postaram się to zrobić tak jak napisał @kubARek, zobacze co z tego wyjdzie, póki co chcąc uzyć DOMContentLoaded (nie działa pod IE), musialem skorzystać ze skryptu 'documentReady' pobranego stąd i pojawila się pewna niejasność. funkcja wywolana przez documentReady łapie dwukrotnie i pojawia sie na dole tekst "DOM Loaded".. dlaczego?

var obrazki = [
				   'obraz1.jpg',
				   'obraz11.jpg',
				   //'obraz2.jpg',
				   //'obraz3.jpg',
				  // 'obraz4.jpg',
				  // 'obraz5.jpg',
				  // 'obraz6.jpg',
				 //  'obraz7.jpg',
				 //  'obraz8.jpg',
				   ];

function Laduj () {
	for(x=0; x< obrazki.length; x++) {
		   $.cacheImage(obrazki[x])
	alert(obrazki[x])
	}
}

documentReady(Laduj);
</script>
</head>
<body>
<div id="obraz"></div>
</body>
</html>

PS. jQuery jeszcze nie kapuje, na razie do tego problemu staram sie wykorzystac, także jak nie trzeba to czysta javascript do mnie :P

0

Ale po co robisz to DOM Loaded? Po co Ci to? Co się stanie złego jeśli to wywalisz i po prostu odpalisz Laduj()?

Z tego co widzę w kodzie to cacheImage(obrazki) powinno dać taki sam efekt jak cacheImage(obrazki[x]) w pętli.

PS. W tablicy obrazki nie zostawiaj przecinka za ostatnim (niezakomentowanym) elementem. IE tego nie lubi.

0

bo to jest moj poczatek do preloadera. dlatego DOM Loaded, chcę żeby wywolal funkcje preloadera, tzn podczas ladowania tych obrazków animował sie jakis gifek i pojawiał się procent zaladowania, po zaladowaniu wszystkich bede chcial lagodnie ukryc preloader a pokazac zawartosc strony. chcialbym tez zeby preloader pokazywal sie tylko wtedy gdy obrazkow nie bedzie w pamieci podrecznej przegladarki, a nie za kazdym razem (takie preloadery znajdywalem w sieci, zreszta nie chce za bardzo zrzynać, wolalbym cos po swojemu.. znalazlem jeden ciekawy, ale zachowywal sie anomalnie pod opera, moze wrzuce jego skrypt ale pozniej, nie chce za bardzo mieszac w jednym temacie) dlatego wazne jest dla mnie zeby to ladowanie dzialalo poprawnie. mozliwe ze zle sie za to wszystko zabieram ale jestem na poczatku drogi, na razie mam taki pomysl i taki oto problem: 'jak wczytac wskazane pliki bedace backgroundami bloków do pamieci, zanim strona zostanei wyswietlona'

w dalszym ciagu nie wiem dlaczego documentReady powoduje dwukrotne wyswietlanie 2x alert. i jeszcze ten napis na dole "dom loaded" :|

0

i jeszcze ten napis na dole "dom loaded"
A to kod w pliku documentReady.js:

function init() {
	if (arguments.callee.done) { return; }
	arguments.callee.done = true;
	//your code:
	document.body.appendChild(document.createTextNode('DOM loaded.')); //// <--- tu, o; tę linijkę możesz wywalić
};

I teraz pytanie, dlaczego dwa razy? Otóż, funkcja poprawnie wywołuje się w momencie DOMContentLoaded, ale w documentReady.js znalazłem taki kwiatek: window.onload = callback;Dzięki temu callback dodawany jest zarówno do DCL, jak i onLoad, co powoduje dwukrotne jej wywołanie :) Żeby to naprawić, po prostu usuń w/w linijkę. Albo dodaj do funkcji Laduj() dwie początkowe linijki kodu, jakie są w funkcji init(). Obiekt arguments.callee w kontekście funkcji jest właśnie daną funkcją :P Czyli w tym przypadku arguments.callee === init. We wnętrzu funkcji Laduj(), arguments.callee będzie samą funkcją Laduj.

0

@DewREW:
Weź wywal cały ten skrypt documentReady. Skoro @kubARek znalazł w nim takie coś, to cholera wie co tam jeszcze siedzi. Jeśli sam nie masz wiedzy odpowiedniej do debugowania czy choćby rozpoznania, czy jakiś skrypt jest OK, to korzystaj z jak najmniejszej liczby skryptów -- ale takich, o których wiesz na pewno, że działają. jQuery do nich należy. I już o go używasz, prawda? Nie ma najmniejszego sensu dodawanie kolejnego skryptu, który dublowałby działanie innego, który już masz dodany do strony. jQuery ma potrzebą funkcjonalność, więc z niej skorzystaj, a nie zwiększaj rozmiaru strony kolejnym badziewiem.

W jQuery osiągniesz pożądany efekt w ten sposób:

$(document).ready(Laduj);

Chyba że poradzisz sobie innymi, specjalistycznymi, mniejszymi skryptami. I będziesz mógł usunąć jQuery. Wtedy to zrób -- jQuery zajmuje parędziesiąt KB i jeśli potrzebujesz np. samego ready(), to nie opłaca się go używać. Korzystasz też z wtyczki do jQuery o nazwie imageCache, ale to też mała wtyczka -- możesz napisać jej odpowiednik samodzielnie, zgodnie z radami kubARka. Wtedy będziesz mógł wywalić jQuery. Ale jeśli chcesz tę bibliotekę zostawić, to wykorzystaj ją w maksymalnym stopniu.

edit: Wracając do tego skryptu documentReady. Dopiero teraz na niego spojrzałem. Jest napisany przez Piotrka Petrusa. Nie powinien więc być lipny, czy nie działający. Wątpię, by Piotrek wypuścił jakiś badziew. Jak będę miał chwilę, to przeanalizuje co jest nie tak i dlaczego. Niemniej jednak to, co napisałem, pozostaje słuszne: skoro masz jQuery, to nie dodawaj kolejnego skryptu, tylko użyj funkcji z jQuery tam gdzie to możliwe.

0

wyglada na to ze w skrypcie dotyczacym documentReady, ostatnie linie kodu, tj.

function init() {
        if (arguments.callee.done) { return; }
        arguments.callee.done = true;
        //your code:
        document.body.appendChild(document.createTextNode('DOM loaded.')); //// <--- tu, o; tę linijkę możesz wywalić
};

documentReady(init);

są przykladem korzystania z tego skryptu :) bez tych ostatnich linii chyba działa jak dzialac powinno.

wracajac do mojego dokumentu, ktory w tej chwili dokument wyglada tak:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=ISO-8859-2">
<title>Dokument bez nazwy</title>
<!--[if IE]><link rel="stylesheet" type="text/css" href="css.css" /><![endif]-->
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="document.ready.js"></script>


<style type="text/css">
* { margin: 0 auto; padding: 0;}
#obraz { background-image:url(Obraz1.jpg); display: block; height: 800px; width: 600px;}
#obraz:hover {background-image:url(Obraz2.jpg);} </style>

<script type="text/javascript"> 
function dodajZdarzenie(odnosnik, zdarzenie, funkcja){
	if (odnosnik.addEventListener) {
		odnosnik.addEventListener(zdarzenie, funkcja, false); 
	}
	else { 
		odnosnik.attachEvent("on"+zdarzenie, funkcja); 
	}
}


function zmien () {

document.getElementById('obraz').style['backgroundImage'] = "url(Obraz2.jpg)";
}

	var nazwy = [
				   'Obraz1.jpg',
				   'Obraz11.jpg',
				   'Obraz2.jpg',
				   'Obraz3.jpg',
				   'Obraz4.jpg'
				  // 'obraz5.jpg',
				  // 'obraz6.jpg',
				 //  'obraz7.jpg',
				 //  'obraz8.jpg'
				   ];
	var obrazki = [];
	var ilosczaladowanych = 0;
	var postep = 0;
	
function Laduj () {
	if (arguments.callee.done) { return; }
	arguments.callee.done = true;
	for(var x=0; x< nazwy.length; x++) {
   	obrazki[x] = new Image();
   	obrazki[x].src = nazwy[x];
	ilosczaladowanych++;
	postep = Math.round(ilosczaladowanych*100/nazwy.length)+"%";
	alert(postep);
	if (postep == "100%") {
	//document.getElementById('obraz').style['backgroundImage'] = "url(Obraz2.jpg)";
	}
	}
	
//dodajZdarzenie(document.getElementById('obraz'),'mouseover', zmien);
}



documentReady(Laduj);
</script>
</head>

<body>
<div id="obraz"></div>
</body>
</html>

zmienilem sposob ladowania obrazków tak jak podał @kubARek. ale czy to na pewno działa? jezeli zmieniac tło przez druga funkcje z zapisem 'document.getElementById('obraz').style['backgroundImage'] = "url(Obraz2.jpg)";' w FF wyglada to calkiem dobrze, ale np gdy robie to przez "hover" wydaje mi sie ze przerwa przy podmianie obrazków nadal wystepuje. z kolei w IE6, caly skrypt interpretowany jest poprawnie ale co z tego skoro przy kazdej mozliwej podmianie obrazków jest oczekiwanie na jego wczytanie, mimo ze skrypt mial je zaladowac do pamieci. jest jakiś sposób pozwalający jednoznacznie stwierdzić że wskazane pliki na pewno są już załadaowane do pamięci? moglby ktorys z panów sprawdzic jak to prezentuje sie u niego? bo moze tylko mnie sie wydaje ze coś jest nie tak..

0

Sprawdziłem ten kod, z małym wyjątkiem. Zamiast documentReady(Laduj); dałem po prostu Laduj();

W Firefoxie, po sprawdzeniu Firebugiem* - najechanie na

zmienia obrazek, nie pobierając go przy tej zmianie. Czyli tak jak być powinno.
Pod IE8 podobnie, nie widać, żeby się obrazek ładował.. Jeśli chodzi o IE6, to jeśli naprawdę nie musisz, to nie przejmuj się dziwactwami tej przeglądarki, gdyż na szczęście odchodzi w niebyt :)</p>

*zainstaluj i sam zobaczysz, świetna sprawa z tym dodatkiem :) Zakładka Net mówi o tym, jakie pliki są aktualnie ściągane, ile czasu zajęło, jaki rozmiar, etc.

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