Felix Riesterer: Das Script (Teil 3)

Beitrag lesen

Im dritten Teil folgt nun die Konstruktor-Funktion, die das Kernstück unseres ganzen Scripts bildet, denn das Framework ist - wie der Name schon sagt - nur der Rahmen drumherum, der die einzelnen Fader verwaltet, dier Konstruktor-Funktion dagegen ist jedoch die "Fabrik", in der einzelne Fader-Objekte hergestellt werden.

Wieder ein paar Überlegungen, bevor wir unsere Konstruktor-Funktion aufbauen:

1.) Eigenschaften:     a) Alle unsere über die init()-Funktion übergebenen Eigenschaften müssen verarbeitet werden.     b) Sollten manche Eigenschaften nicht übergeben worden sein, dann gelten die Voreinstellungen aus unserem FaderFramework-Objekt (wie z.B. "viewTime", "fadeStep", "autostart" oder "random").     c) Unser Fader benötigt eine Playlist (ein Array - Eigenschaft "playList"), denn die Bilder sollen ja auch zufällig wiedergegeben werden.     d) Wenn eine Playlist abläuft, dann brauchen wir einen Zeiger auf das aktuell angezeigte Bild, damit wir das vorhergehende ausblenden können: "counter".     e) Bei einer zufälligen Wiedergabe sollten wir nach einem Durchlauf eine neue Playlist erstellen, da sonst der Zufall sehr regelmäßig würde.     f) Wenn wir eine neue Playlist erstellen, dann fehlt uns die Möglichkeit, das "alte Bild" auszublenden, da wir in der neuen Playlist nicht mehr wissen, welches das alte Bild war. Daher brauchen wir auch die alte Playlist: "oldPlayList".     g) Wir wollen unsere Slideshow anhalten können. Dazu brauchen wir eine Eigenschaft "stopped", die von unseren Funktionen berücksichtigt wird.     h) Unser Fader läuft in einem <span>-Element ab. Dieses Element speichern wir unter der Eigenschaft "element".

2.) Funktionen (Methoden):     a) fade() wird unsere Überblendungsfunktion werden. Sie blendet das aktuelle Bild (auf das unser Zähler zeigt) ein und blendet das alte Bild (also das, worauf der Zähler vorher gezeigt hat) aus.     b) next() wird unsere Funktion, um einen Bilderwechsel anzustoßen.         Sie erhöht den Zeiger (oder veranlasst, dass eine neue Playlist erzeugt wird, mit dem Zeiger wieder auf Null) und ruft fade() auf.         Bei angehaltenem Fader darf diese Funktion aber kein nächstes Bild anzeigen lassen. Es sei denn wir möchten das sozusagen "gewaltsam" für einen einzelnen Schritt. Dazu benötigt sie einen zu übergebenden Parameter der "true" sein muss. Fehlt er, dann ist das im Prinzip dasselbe, als hätten wir "false" übergeben.     c) stop() wird eine Funktion, die die Eigenschaft "stopped" auf "true" setzt. Dadurch wird die Funktion next() ausgebremst. Eine bereits angefangene Überblendung soll aber zu Ende ablaufen. Daher wird fade() diese Eigenschaft ignorieren.     d) start() ist das Gegenstück zu stop() und setzt die Eigenschaft "stopped" auf "false". Außerdem startet sie die Slideshow, indem sie auch next() aufruft.     e) createPlaylist() verwenden wir, um eine Playlist zu generieren.

3.) Die Herstellung eines Faders     a) Ein Fader wird ja mit seiner ID unter FaderFramework.faders abgelegt werden. Das darf nur erfolgen, wenn folgende Bedingungen erfüllt sind:         - Es wurde eine ID übermittelt.         - Es existiert ein HTML-Element mit der angegebenen ID im Dokument.         - Es existiert noch kein Fader mit dieser ID.         - Es sind mindestens zwei Bilder zum Überblenden vorhanden.     b) Bei der erfolgreichen Herstellung eines Faders muss das originale <img />-Element im Dokument durch ein <span>-Element ersetzt werden, welches wir ja unter "element" als Eigenschaft des Faders abspeichern.

Diese Überlegungen setzen wir in den einzelnen Funktionen um. Beginnen wir mit der einfachsten, mit stop():

this.stop = function () {
    this.stopped = true;
};

Das war ja einfach. Schauen wir uns die nächst kompliziertere an, start():

this.start = function () {
    this.stopped = false;
    this.next();
};

Aha. Jetzt bezieht sich start() irgendwie auf next(). Schauen wir uns next() an:

this.next = function (single) {
    // "single" ist true oder false und dient dazu, einen einmaligen Wechsel zu ermöglichen, ohne eine Slideshow zu starten. Wird kein Parameter übergeben, dann wird single nicht als true interpretiert.
    if (single) {
        this.stopped = true;
    }

    // wurde der Fader angehalten?
    if (this.stopped && !single) {
        return; // Ja -> keinen Bildwechsel durchführen!
    }

    // Counter weiterzählen (oder zurücksetzen)
    this.counter = (this.counter < this.playList.length -1) ? this.counter +1 : 0;

    // Neue Playlist fällig?
    if  (this.counter == 0) {
        // neue Playlist generieren
        this.oldPlayList = this.playList; // aktuelle Playlist speichern
        this.createPlayList(); // neue aktuelle Playlist erstellen
    }

    // Fading einleiten
    this.fade();
};

Bevor wir zum Interessantesten kommen, hier die Funktion zum Generieren einer Playlist:

// Playlist generieren (enthält nur die Nummern der Bilder)
this.createPlayList = function () {
    this.playList = new Array();

    if (this.random) {
        // zufällige Reihenfolge
        while (this.playList.length < this.images.length) {
            vorhanden = false; // Zufallszahl bereits vorhanden?
            r = Math.floor(Math.random() * (this.images.length));
            for (i = 0; i < this.playList.length; i++) {
                if (r == this.playList[i]) {
                    vorhanden = true;
                }
            }

            if (!vorhanden) {
                this.playList[this.playList.length] = r;
            }
        }

    } else {
        // geordnete Reihenfolge
        for (i = 0; i < this.images.length; i++) {
            this.playList[i] = i;
        }
    }
};

Und jetzt kommt der Fading-Vorgang:

// Fade-Funktion für den Bilderwechsel (jeder Aufruf entspricht einem Fading-Schritt)
this.fade = function (step) {
    var imgs = new Array(), v;

    // Wenn kein Wert übertragen wurde, dann muss das Fading von vorne durchgeführt werden
    step = (!step) ? 0 : step;

    // Das letzte Bild steht in der Liste vor dem aktuellen (falls dieses ganz am Anfang steht, gilt das letzte der alten Playlist)
    imgs[0] = (this.counter == 0) ? this.images[this.oldPlayList[this.oldPlayList.length -1]] : this.images[this.playList[this.counter -1]];

    // Das neue Bild ist das, auf welches der Counter zeigt
    imgs[1] = this.images[this.playList[this.counter]];

    for (i = 0; i < imgs.length; i++) {
        v = (i == 0) ? (100 - step) : step;
        imgs[i].style.opacity = v/100;
        // IE?
        if (imgs[i].style.filter != "undefined") {
            imgs[i].style.filter = "alpha(opacity=" + v + ")";
        }
    }

    step += this.fadeStep;

    if (step <= 100) {
        // nächsten Fade-Schritt ausführen
        window.setTimeout(""
            + "FaderFramework.faders."
            + this.id
            + ".fade("
            + step
            + ");",
        1);
    } else {
        // Bildübergang abgeschlossen -> nach der Pause nächstes Bild
        window.setTimeout(""
            + "FaderFramework.faders."
            + this.id
            + ".next();",
        this.viewTime);
    }
};

Jetzt brauchen wir im Konstruktor nur noch regeln, dass das originale HTML-Element mit der übertragenen ID (das <img />-Element) mit unserem <span>-Element ersetzt wird.

Fader: function (einstellungen) {
    /*
        In diesem Konstruktor verweist "this" immer auf das zu erzeugende Objekt - vorausgesetzt,
        dieser Konstruktor wird mit dem Schlüsselwort "new" aufgerufen, z.B. var a = new this.Fader()
    */

    // wie "einstellungen" aussehen muss, siehe Funktion "init"!
    var className, imgs, i, r, vorhanden;

    // Darf eventuell kein Fader eingerichtet werden?
    if (
        // keine ID (oder ein Leerstring) übergeben
        !einstellungen.id
        ||
        // kein HTML-Element mit dieser ID vorhanden
        !document.getElementById(einstellungen.id)
        ||
        // für diese ID ist bereits ein Fader eingerichtet
        FaderFramework.faders[einstellungen.id]
        ||
        // weniger als zwei Bilder angegeben
        einstellungen.images.length < 2
    ) {
        // also gibt es keinen Fader für diesen init-Aufruf
        return false;
    }


    // Einstellungen des Faders vornehmen
    this.id = einstellungen.id;
    this.images = new Array(); // Bilder werden hier nicht als Zeichenketten, sondern später als HTML-Elementobjekte abgelegt...
    this.random = einstellungen.random ? einstellungen.random : FaderFramework.random;
    this.autostart = (typeof(einstellungen.autostart) != "undefined") ? einstellungen.autostart : FaderFramework.autostart;
    this.viewTime = einstellungen.viewTime ? einstellungen.viewTime : FaderFramework.viewTime;
    this.fadeStep = einstellungen.fadeStep ? einstellungen.fadeStep : FaderFramework.fadeStep;
    this.stopped = false; // hiermit kann später der Fader angehalten werden
    this.playList = new Array(); // Wiedergabeliste
    this.oldPlayList = [0]; // vorherige Wiedergabeliste (besteht aus einem einzigen Bild)
    this.counter = 0; // aktuell angezeigtes Bild (Zähler für Playlist)


    // DOM-Baum des HTML-Dokumentes auf den Fader vorbereiten

    // <span>-Element als Container erzeugen und mit der Fader-Klasse ausrüsten
    this.element = document.createElement("span");
    this.element.className = FaderFramework.className;

    // vor das ursprüngliche Bild setzen
    i = document.getElementById(this.id); // ursprüngliches Bild
    i.parentNode.insertBefore(this.element, i);

    // ursprüngliches Bild entfernen
    i.parentNode.removeChild(i);

    // Bilder aus der Liste zu echten Bildobjekten machen und ins <span>-Element einhängen
    for (i = 0; i < einstellungen.images.length; i++) {
        this.images[i] = document.createElement("img");
        this.images[i].src = einstellungen.images[i];
        this.images[i].alt = "";

        // Alle Bilder, außer dem ersten, müssen positioniert werden, damit sie nicht neben oder unter dem ersten angezeigt werden.
        if (i > 0) {
            this.images[i].className = "next";

            // Volle Durchsichtigkeit einstellen (erstes Bild soll ja gleich angezeigt werden
            this.images[i].style.opacity = 0;
            // IE?
            if (this.images[i].style.filter != "undefined") {
                this.images[i].style.filter = "alpha(opacity=0)";
            }
        }

        // einhängen
        this.element.appendChild(this.images[i]);
    }


    /*
        Funktionen (Methoden) des Faders definieren!
    */
    // wurde oben bereits behandelt

    // Playlist erzeugen
    this.createPlayList();

    // fertigen Fader zurückgeben
    return this;
}

Damit ist unser Fader-Bauplan im Prinzip fertig und unsere onload-Funktion kann ihn benutzen, um die mit init()-Angeforderten Fader auch zu erstellen.

Unser fertiges JavaScript kommt im nächsten Post, denn ich bin der Forensoftware wieder etwas zu geschwätzig. ;-)

Liebe Grüße,

Felix Riesterer.

--
ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
3 52

Fader zum Bilder überblenden - ein kleiner Lehrgang

Felix Riesterer
  • javascript
  1. 2

    Das Script (Teil1)

    Felix Riesterer
    1. 1

      Das Script (Teil1) - Reflektion zum Code

      Felix Riesterer
      1. 0
        bosselmann
        1. 0
          Felix Riesterer
    2. 2

      alternativer loesungsansatz (teil1): model, view, ...

      peterS.
      1. 0

        alternativer loesungsansatz (teil2): .., controller.

        peterS.
        1. 0

          alternativer loesungsansatz (teil2): code review (teil 1?)

          peterS.
          1. 0

            alternativer loesungsansatz (teil2): code review (teil 2?)

            peterS.
            1. 0

              alternativer loesungsansatz (teil2): code review (teil 3)

              peterS.
      2. 0
        Felix Riesterer
        1. 0

          konkurrierende ansaetze

          peterS.
          1. 0
            Felix Riesterer
  2. 0

    SELFHTML-Artikel statt Forumsbeitrag?

    Vinzenz Mai
    • meinung
    1. 0
      Felix Riesterer
      1. 0
        Siechfred
        1. 0
          Felix Riesterer
        2. 0

          SELFHTML-Artikel - bin schon fleißig dabei!

          Felix Riesterer
        3. 0

          Artikel eingeschickt

          Felix Riesterer
          1. 0
            Siechfred
            • menschelei
            1. 0
              dedlfix
            2. 1
              Felix Riesterer
    2. 0
      Felix Riesterer
  3. 0

    Das Script (Teil 2)

    Felix Riesterer
  4. 0

    Das Script (Teil 3)

    Felix Riesterer
  5. 0

    Das Script (Endergebnis)

    Felix Riesterer
    1. 1
      molily
      1. 0
        Felix Riesterer
        1. 0
          Struppi
          1. 0
            Felix Riesterer
            1. 0
              bosselmann
              1. 0
                Felix Riesterer
                1. 0

                  Falscher Thread-Zweig...:-/

                  Felix Riesterer
                  1. 0

                    Verständnisfragen

                    bosselmann
                    1. 0
                      Felix Riesterer
                      1. 0
                        bosselmann
                        1. 0
                          Felix Riesterer
                          1. 0
                            bosselmann
                            1. 0
                              Felix Riesterer
                              1. 0

                                Skriptergänzung

                                bosselmann
                                1. 0
                                  Felix Riesterer
                                  1. 0

                                    Skriptergänzung (finale Version)

                                    bosselmann
                                    1. 0
                                      Felix Riesterer
  6. 0
    Felix Riesterer
    1. 0
      Beat
      1. 0

        Review-Version des Lehrgangs

        Felix Riesterer
        1. 0
          Beat
          1. 0
            Felix Riesterer
        2. 0
          Struppi
          1. 0
            Felix Riesterer
            1. 0
              Struppi
              1. 0
                Felix Riesterer