jQuery: Bilder nachladen, hohe CPU Last

chris4712

Erfahrenes Mitglied
Hallo in die Runde!

In einem Projekt werden viele DIV Container erzeugt, die je ein kleines Bild als Hintergrundbild haben. Die Container werden anhand einer Datenbankabfrage erstellt. Wenn nun 500 Container auf einmal ein Hintergrundbild laden, geht das in die Hose.
Also war meine Idee: Immer nur die Bilder zu laden die grade angezeigt werden. Da ich mit "mCustomScrollbar" arbeite, habe ich einfach das Event "whileScrolling" verwendet, was meine Funktion (siehe unten) ausführt.

Ich gebe also z.B. 100x diese Zeile aus (ID passt sich an):
PHP:
<div class="ThumbContainer ThumbNotLoaded" id="$Picture["ID"]"></div>

Die JavaScript Funktion, die beim Scrollen ausgeführt wird, schaut so aus:
Code:
function ShowThumbs(scrollerTop) {
  var scrollerHeight = $("#ImageSurveyArea").height(); // Liest die Höhe des Bereiches aus, in dem die Bilder angezeigt werden

  $(".ThumbNotLoaded").each(function () { // Läuft jedes Bild durch was noch nicht geladen wurde
    // Wenn das Bild sich im sichtbaren Bereich befindet
    if ($(this).position().top >= scrollerTop && $(this).position().top <= (scrollerHeight+scrollerTop)) {
      $(this).html('<div class="ThumbImage" style="background-image: url(\'functions/PictureManager/Thumbnail.php?ID='+$(this).attr('id')+'\')"></div>'); // Neuen DIV Container erzeugen, der das Bild als Hintergrundbild hat
      $(this).removeClass("ThumbNotLoaded"); // Klasse entfernen um zu signalisieren das Bild geladen wurde
    }
  });
}

Soweit so gut. Klappt wunderbar. Jedoch ist die CPU Last irgendwas bei 30% (Intel Core i7). Kann also nicht der optimale Code sein. Zumal nicht nur 100 Bilder sondern gerne auch mal 1000 Bilder angezeigt werden.

Wie könnte ich das Konstrukt optimieren?

Vielen Dank fürs Nachdenken und schöne Grüße!

Christian
 
Hi,

ich würde an unterschiedlichen Stellen versuchen zu optimieren.

1. Aufrufen des scroll-Handlers nur, wenn sich die Scrollposition deutlich verändert hat (z.B. 30 Pixel) => damit können sicherlich zahlreiche unnütze Funktionsaufrufe vermieden werden => das würde die Last im Handler reduzieren, ständig die Elemente im DOM zu ermitteln, die noch kein Hintergrundbild-Element besitzen

2. Häufiger benutzte Anweisungen (z.B. $(this)) in Variablen speichern => damit kann vermieden werden, dass ständig das gleiche Element referenziert werden muss
Code:
$(".ThumbNotLoaded").each(function () { // Läuft jedes Bild durch was noch nicht geladen wurde
    var $this = $(this),
        top = $this.position().top;

    // Wenn das Bild sich im sichtbaren Bereich befindet
    if (top >= scrollerTop && top <= (scrollerHeight+scrollerTop)) {
        $this.html('<div class="ThumbImage" style="background-image: url(\'functions/PictureManager/Thumbnail.php?ID='+$this.attr('id')+'\')"></div>'); // Neuen DIV Container erzeugen, der das Bild als Hintergrundbild hat
        $this.removeClass("ThumbNotLoaded"); // Klasse entfernen um zu signalisieren das Bild geladen wurde
    }
});

3. Zu guter Letzt würde ich vermeiden, Elemente neu zu erstellen, die ich auch im HTML anlegen bzw. bereitstellen kann.
PHP:
<div class="ThumbContainer ThumbNotLoaded" id="$Picture["ID"]"><div class="backgroundContainer"></div></div>
Innerhalb der each-Anweisung kann dann auf das bereits existierende Element zugegriffen werden und das Erstellen und Einhängen in den DOM kann entfallen.
Code:
$(".ThumbNotLoaded").each(function () { // Läuft jedes Bild durch was noch nicht geladen wurde
    var $this = $(this),
        $elem= $this.children().eq(0),
        top = $this.position().top;

    // Wenn das Bild sich im sichtbaren Bereich befindet
    if (top >= scrollerTop && top <= (scrollerHeight+scrollerTop)) {
        // Hintergrundbild an Element zuweisen
        $elem.css({
            'background-image': 'url(functions/PictureManager/Thumbnail.php?ID=' + $this.attr('id') + ')'
        });
        // Klasse entfernen, um zu signalisieren, dass das Bild geladen wurde
        $this.removeClass("ThumbNotLoaded");
    }
});

Kannst das ja mal ausprobieren und hier mitteilen, ob und welchen Erfolg das gebracht hat.

Ciao
Quaese
 
Zurück