DiaShow mit JavaScript

Post Reply
Message
Author
moko

DiaShow mit JavaScript

#1 Post by moko »

Hallo,

habe eine JavaScript Dia Show.
Allerdings werden hier vor dem Anzeigen erst alle Bilder geladen (preload).

Was muss wie geändert werden, damit die Bilder erst geladen werden, wenn sie angezeigt werden sollen?

Ich möchte aber kein Array mit allen aufgeführten Dateinamen. Dafür ist der Aufwand zu hoch.

Hier mein jetziges Script:

Code: Select all

<script language="JavaScript" type="text/JavaScript">
<!--
var img = new Array&#40;&#41;; 
var start = null;      
var counter = 1;       
var anzahl_bis_hier;   
var anzahl_bilder;     
var fileending;
var filesource;       

anzahl_bilder = 192; 
filesource = "a";
filetype = ".jpg";      
var delayTime = 5000;    

if&#40;document.images&#41;
&#123;
	i=1;
	while&#40;i<= anzahl_bilder&#41;
   &#123;
     img&#91;i&#93; = new Image&#40;&#41;;
     img&#91;i&#93;.src = filesource + i + filetype;
     i++;
   &#125;
&#125;

function anim&#40;&#41;
&#123;
   counter++;
   document.getElementById&#40;"pic1"&#41;.src = img&#91;counter&#93;.src;
   if&#40;counter == anzahl_bilder&#41;
    counter = 0; 
&#125;

function slide&#40;&#41;
&#123;
   with&#40;document.form1&#41;
   &#123;
   start = setInterval&#40;"anim&#40;&#41;", delayTime&#41;;
   go.disabled = true;
   stop.disabled = false;
   &#125;
&#125;

function pause&#40;&#41;
&#123;
   clearInterval&#40;start&#41;;
   document.form1.go.disabled = false;
   document.form1.stop.disabled = true;
&#125;
//  End -->
</script>

----------------------------------------------

<script language="JavaScript" type="text/JavaScript">
<!-- 
setTimeout&#40;"slide&#40;&#41;,5"&#41;; 
//-->
</script>
</td></tr>
<tr><td><div align="right">
<input type=button value="go" name=go onClick="slide&#40;&#41;;">
<input type=button value="pause" name=stop onClick="pause&#40;&#41;;">
</div>

moko

#2 Post by moko »

habe es inzwischen selbst hinbekommen.

für kleine bis ewig lange slideShows eignet sich nun dieses javascript.

Code: Select all

//im head-bereich

<script language="JavaScript" type="text/JavaScript">
<!--
var img = new Array&#40;&#41;; 
var start = null;      
var counter = 1; 
var i = 1;        
var number_pics;     
var fileending;
var filesource;       

number_pics = 100  // Gesamtanzahl der Bilder
filesource = "a"; //Bildernamen sind somit a1.jpg, a2.jpg, ...
filetype = ".jpg";      
var delayTime = 5000;    //Zeit in ms


function animate&#40;&#41;
&#123;
	i++;
   img&#91;i&#93; = new Image&#40;&#41;;
   img&#91;i&#93;.src = filesource + i + filetype;
   	 if&#40;i == number_pics&#41;
    		i = 0; 
   	
   counter++;
   document.getElementById&#40;"pic1"&#41;.src = img&#91;counter&#93;.src;
   if&#40;counter == number_pics&#41;
    counter = 0; 
&#125;

function slide&#40;&#41;
&#123;
   with&#40;document.form1&#41;
   &#123;
   start = setInterval&#40;"animate&#40;&#41;", delayTime&#41;;
   go.disabled = true;
   stop.disabled = false;
   &#125;
&#125;

function pause&#40;&#41;
&#123;
   clearInterval&#40;start&#41;;
   document.form1.go.disabled = false;
   document.form1.stop.disabled = true;
&#125;
//  End -->
</script>

---------------------
// im body-bereich

<img id="pic1" src="a1.jpg" width="500" height="375" border="0" alt="pictures. animated with java script."><br>
<script language="JavaScript" type="text/JavaScript">
<!-- 
setTimeout&#40;"slide&#40;&#41;,5"&#41;; 
//-->
</script>


User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#3 Post by Janka »

Das letztere Skript hat ein Speicherleck, da du mit jedem Aufruf von animate ein neues Image-Objekt erzeugst, dieses aber nie wegwirfst.

Vorschlag für die Animate-Funktion:

Code: Select all

function animate&#40;&#41; 
&#123; 
    if&#40;i <= number_pics&#41; &#123;
        img&#91;i&#93; = new Image&#40;&#41;; 
        img&#91;i&#93;.src = filesource + i + filetype; 
        i++; 
    &#125;
        
    counter++; 
    document.getElementById&#40;"pic1"&#41;.src = img&#91;counter&#93;.src; 
    if&#40;counter == number_pics&#41; 
     counter = 0; 
&#125; 
Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

moko

#4 Post by moko »

Danke für den Hinweis.

Ich kann kein Speicherleck erkennen.


Nehme ich deine Variante, funktioniert sie nicht, da i schon auf 1 gesetzt ist und am Anfang erhöht werden muss, da Bild a1.jpg schon angezeigt wird.

Was hälst du von dieser Variante? So läuft es zumindest.

Code: Select all

function animate&#40;&#41;
&#123;
    if&#40;i <= number_pics&#41; &#123;
        i++;
        img&#91;i&#93; = new Image&#40;&#41;;
        img&#91;i&#93;.src = filesource + i + filetype;
      if&#40;i == number_pics&#41;
        i = 0;
    &#125;
       
    counter++;
    document.getElementById&#40;"pic1"&#41;.src = img&#91;counter&#93;.src;
    if&#40;counter == number_pics&#41;
     counter = 0;
&#125; 

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#5 Post by Janka »

Deine letzte Version hat *wieder* ein Speicherleck. Es wird bei jedem Aufruf von animate() mit "new Image()" neuer Speicher für ein Bild angefordert. Dieser Speicher wird niemals freigegeben, da img[] ein globales Array ist. (Ich weißt jetzt aber nicht, ob die Garbage-Collection von Javascript gut genug ist, zu ekennen, dass das Bild, das vor der Zuweisung von img = new Image(); in img referenziert wurde, nun nicht mehr referenziert ist. Meine schlechten Erfahrungen mit Javascript sagen mir aber: eher nicht.)

Was meine Version angeht: Niemand hindert dich daran, i *vor* der Zuweisung eines neuen Bildes zu erhöhen. Dann aber i<= number_pics durch i<number_pics ersetzen.

Was du nicht machen darfst, ist, i jemals wieder zurückzusetzen. Das ist erstens vollkommen unnötig, denn die Bilddateien müssen nur einmal geladen werden, und zweitens braucht jeder Durchlauf dann erneut neuen Speicher für alle Bilder.

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

moko

#6 Post by moko »

Du meinst, mit jedem Durchlauf wird das array vergroessert oder ein neues Array angelegt?

Da kenne ich mich nicht aus.
Ich gehe davon aus, dass ich mit "img" immer wieder auf das gleiche Image zugreife bei jedem Durchlauf und nur 1 Array habe.

Deiner Beschreibung nach habe ich es nicht zum Laufen bekommen.

Es soll ja eine Endlosschleife sein, daher setze ich am Ende den Zähler auf 0. Bild a1.jpg soll ja bei jedem Wiederholen wieder erscheinen. Dass ist sonst nicht der Fall.

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#7 Post by Janka »

"new Image()" ruft den Constructor für ein Image-Objekt auf. Dieses Objekt belegt Speicher. Entfernt man die letzte Referenz auf ein Objekt, wird der Garbage Collector es in einer ruhigen Minute entfernen und den Speicher wieder freigeben.

Leider kann man nicht steuern, wann das passiert, so dass man in die dumme Situation geraten kann, dass man Objekte schneller erzeugt als der Garbage-Collector sie wieder wegwirft. In dem Fall frisst der Javascript-Interpreter im Browser immer mehr Speicher und der Rechner des armen Javascript-Opfers wird immer langsamer...

Also solltest du nicht jedes Mal ein neues Image-Objekt erzeugen, sondern nur die Anzahl, die tatsächlich an Bildern vorliegt.

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

moko

#8 Post by moko »

Ich werde es, soweit ich kann, berücksichtigen, danke.

Nach einigen Testläufen kann ich allerdings keinen weiteren Anstieg des Speicherverbrauches feststellen, wenn die Bilder wiederholt werden.

Vielleicht tritt der Effekt ja bei sehr grossen Datenmengen auf.
Dann sollte man den Speicherverbrauch auf jeden Fall im Blick behalten.

Eine free()-Funktion gibt's in JavaScript sicherlich nicht, oder?

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#9 Post by Janka »

Der Effekt sollte auftreten, wenn animate() sehr oft in kurzer Zeit aufgerufen wird. Wobei "kurze Zeit" sich nach der Systemlast beim Anwender richtet. Und natürlich ist das auch vom Browser abhängig.

free() oder destroy() gibt's bei Javascript nicht, das soll ja der Garbage-Collector machen, sobald ein Objekt nirgendwo mehr benutzt wird. Leider verführt das dazu, dass die meisten Javascript-Programmierer sich keine Gedanken über den Speicherbedarf machen, und so sind da eine Menge kaputter Skripte im Umlauf.

Übrigens ist deine Version auch wenn der beschriebene Fehler nicht auftritt ressourcenfressender als notwendig, denn die Bilder werden ja bei jedem Durchlauf von animate() neu vom Webserver geladen. Genau das sollte das Laden am Anfang ja vermeiden -- wenn man auf eine geringe Belastung des Webservers keine Wert legt, braucht man das ganze Array-Konstrukt nicht.

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

moko

#10 Post by moko »

Bei mir wurden die Daten nur einmal geladen (Firefox).

Beim Looping hat sich Firefox aus dem Cache bedient und nur noch gelegentlich und sehr geringen Traffic verursacht.

Sicher mag das technisch so sein, wie du schreibst.
Einen negativen Effekt konnte ich bei mir bisher noch nicht feststellen. Wenn ich mehr Durchblick habe, optimiere ich den Code.

Als vorher die gesamten Daten auf einmal geladen werden mussten, lahmte der Rechner schon gewaltig und das ist unzumutbar.

Post Reply