0t1 steckt noch in den Kinderschuhen.

Durch Scrollen steuerbare Animation

Eine Animation oder ein Video, welches beim runter Scrollen weiter und beim hoch Scrollen zurück spult, wessen Progress von der Scroll-position abhängig ist und wessen Abspielgeschwindigkeit durch einen Regler verstellbar ist (optional). Hier ist unsere Methode dies in deine Website zu implementieren.

WOOOWW

Beginne wie immer im Head-Tag

noch machen wir alles wie gewohnt

Der Head-Tag und das Grundgerüst für unsere HTML-Datei ist erstmal wie gewohnt, jedoch schreiben wir einige Zeilen CSS in den Head mittels eines »style«-Tags, zusätzlich zu unserer verlinkten CSS Datei. Welchen Nutzen das hat, schauen wir uns später an.

<!DOCTYPE html>
<html>
  <head>   
    <meta charset="utf-8">
    
    <title>cooler Scrolleffekt</title>
    
    <link rel="stylesheet" href="style.css"> 

     <style> 
         html {                       /*  Dokumentenhöhe wird hier erstmal auf 500vh         */ 
         height: 500vh;               /*  gelegt, 1vh entspricht 1% der Viewporthöhe,        */
         }                            /*  bei diesem Wert ist die Animations-                */
     </style>                         /*  geschwindigkeit "normal".                          */
  </head>                      
  
 /* Zusätzlich zum externen Style-sheet hier ein 
    inline-style, damit der geschwindigkeits-Regler 
    später auf diesen Wert zugreifen kann. */

Wir erschaffen unsere Leinwand

oder Flipbook, je nachdem wie man es sehen will.

Wie in einem klassischen Kinofilm, findet unsere Animation auf einer Leinwand statt, diese kann man mit dem einfachen Tag »canvas« erstellen. Der canvas-Tag ist durch javascript steuerbar und kann sich selbst aktualisieren und somit mehrere Bilder hintereinander anzeigen, ohne dass man die Website neu laden muss oder CSS animationen anwenden muss.

<body>

<canvas id="Leinwand" />    /* Die ID ist später nützlich, damit der Javascript code unsere Leinwand 
                            identifizieren kann*/

</body>

Für die Animation an sich war's das an HTML-code, schauen wir uns doch als nächstes an, was wir in unserem externen Style-sheet mit dem Canvas machen:

body {

    background: #FF3344;    /* Hintergrundfarbe kann man beliebig wählen, nehmt 
                               einfach das, was am besten zu eurer Animation passt 
                               oder einach was euch gefällt */
    height: 500vh;            

}

canvas {

    position: fixed;        
    left: 50%;
    top: 50%;
    max-height: 100vh;
    max-width: 100vw; 
    transform: translate(-50%, -50%);

}

»position: fixed« fixiert die Leinwand auf dem Bildschirm, sodass sie immer an der gleichen Stelle sichtbar bleibt, egal wie lange man scrollt.

Die restlichen Attribute positionieren die Leinwand auf unserem Bildschirm mittig, mit diesen könnt ihr ein wenig herumprobieren, vorallem wenn ihr für etwas anderes geht, als ein großes Hero-banner.

Bringen wir die Leinwand zum Leben!

mithilfe von Javascript

Wie schon erwähnt, wird unsere Leinwand durch Javascript-Befehle gesteuert. Einfach ausgedrückt, sagt der Code der Leinwand, dass sie das jeweils nächste Bild anzeigen soll. Davor müssen wir die Bilder aber erstmal holen. In der Zip-Datei im Download befindet sich ein Ordner mit der Animation, die wir erstellt und benutzt haben. Wenn ihr eine eigene benutzen wollt, dann könnt ihr das auch machen. Dazu exportiert ihr einfach eure Animation als Einzelbilder in einen Ordner und gebt diesen dann als Quelle im Code an.

Unser gesamter Java script code befindet sich in der HTML Datei, das bietet sich an, da in ihr bisher sonst nur ein anderer Tag ist. Dazu öffnet man einfach einen <script> -Tag und schreibt seinen code dort hinein.

Wir beginnen unseren Code damit, einige Variablen zu definieren. Diese mögen erstmal banal wirken, jedoch kann javascript nicht ohne weiteres mit den HTML-tags umgehen, weshalb wir ihnen Variablen zuweisen, mit denen Javascript als objektorientierte Programmiersprache arbeiten kann.

<script>



const html = document.documentElement; // diese Konstante stellt einfach das HTML-Dokument an sich dar. 
const FrameAnzahl = 60; // Wir haben genau 60 Bilder, das halten wir hier als konstante fest 
const Leinwand = document.getElementById("Leinwand"); // Das Element mit der ID "Leinwand", welches der Canvas oben ist.
const context = Leinwand.getContext("2d"); // hiermit sagen wir unserer Leinwand, mit welcher Methode sie die Bilder darstellen soll, in dem Fall "2d"

</script>

Als nächstes definieren wir die Variable, die später das aktuelle Bild („Frame") beinhalten wird.

const Framejetzt = index => (
 `Frames/${index.toString().padStart(4, '0')}.jpg`         
);

diese Konstante ist der Frame, also das Bild, was jetz gerade dargestellt werden soll. Die Bilddateien sind im Ordner nach Nummern sortiert (0001, 0002, 0003 etc. ...) Mit dieser Zeile sagen wir unserem Browser auf welchem Dateipfad das Bild liegt, was er gerade "holen" soll.

const img = new Image()    
img.src = Framejetzt(1);  // Oben definiert mit "index", dort wird dann die "!" in der Klammer eingesetzt.
Leinwand.width=1920;     /* Die Dimensionen Der Leinwand*/
Leinwand.height=1080;   
img.onload=function(){

    context.drawImage(img, 0, 0);  // "draw" : zeichne das Bild! 
}

Da wir oben unsere Variablen definiert haben, können wir sie hier erwähnen und unser Code wird wissen, was gemeint ist. Dieser kleine Code-block Lässt die Leinwand das Bild mit der Nummer 1 anzeigen, sobald die Seite geladen wird. Dies müsst ihr nicht unbedingt machen, es ergibt in unserem Beispiel aber am meisten sinn, von Anfang an ein Bild auf der Leinwand zu haben.


Nun kann das nächste Bild kommen

und das danach, und das danach.....

dazu müssen wir unserem Code aber erstmal einen kleinen Zusatz hinzufügen.

const updateBild = index => {
img.src = Framejetzt(index);
context.drawImage(img, 0, 0);
};

Diese Funktion sagt so viel aus wie » zeichne jetzt das Bild mit der Nummer '«.

Welche »Index« eingesetzt wird, soll von unserer Scroll position abhängen, darum kümmern wir uns im nächsten Schritt.

Dazu müssen wir ausrechnen, wo wir uns auf dem Dokument befinden

Ein bisschen Prozentrechnung

Die Rechnung ist eigentlich ganz simpel:

wir nutzen ein Feature von HTML namens ScrollTop, welches uns die Differenz zwischen dem oberen Rand unseres Bildschirmes und dem oberen Rand unseres Dokuments als Wert liefert.

Dieser Wert ist dann am größten, wenn der User ganz nach unten gescrollt hat. Diesen Maximalwert finden wir heraus, indem wir die Bildschirmhöhe von der gesamten scrollbaren höhe abziehen.

Nun können wir die Scrollposition des Users auf unserer Seite berechnen, indem wir den Maximalen Scrolltopwert durch tatsächlichen Wert teilen, was uns den Scrollfortschritt in Prozent liefert.

window.addEventListener('scroll', () => {
const ScrollTop = html.scrollTop;
const maxScrollTop = html.scrollHeight - window.innerHeight;
const Fortschritt = ScrollTop / maxScrollTop          // Rechnung, um die Relative Scrollposition herauszufinden 




const Bildindex = Math.min(
FrameAnzahl - 1,
Math.ceil(Fortschritt * FrameAnzahl)
    );

requestAnimationFrame(() => updateBild(Bildindex + 1))    // Bestelle das nächste Bild 
});

// hier wird ausgerechnet, welche Zahl in den Dateipfad oben eingesetzt werden soll, abhängig von der Scrollposition.

die Variable »Bildindex« liefert uns die Zahl, die oben in das "Index" bei jeder gegebenen Position eingesetzt werden soll. Dazu wird einfach der Scrollfortschritt in Prozent mit der Frameanzahl multipliziert.

Die »Math.min« -Methode ist nur etwas wie ein Failsafe, diese sorgt dafür, dass keine zu hohe Zahl für »Bildindex« eingesetzt wird. Sollte durch einen Fehler oder sonstigem die Rechnung nicht mehr aufgehen, wird stattdessen in unserem Beispiel das vorletzte Bild im Ordner angezeigt. Welches Bild dabei angezeigt wird, kann je nach Animation und Anlass festgelegt werden.

Dies alles steht in der addEventlistener-Methode, die, wie der Name schon sagt, nach einem bestimmten Ereignis horcht.
In diesem Fall wartet sie darauf, dass der User scrollt. und sobald dies geschieht, wird alles, was in der Klammer steht, ausgeführt, wie wir es gerade behandelt haben.

requestAnimationFrame(() => updateBild(Bildindex + 1))    // Bestelle das nächste Bild 
});

Diese Funktion kann man sich wie den Motor, oder das Hamsterrad des ganzen Canvas' vorstellen. Sie steht noch im Eventlistener, was bedeutet, dass jedes mal, wenn gescrollt wird, das nächste Bild bestellt wird.

Vollständigkeitshalber:

Damit ihr nicht immer die einzelnen Code-blöcke suchen müsst, haben wir eine ZIP-Datei zum Download angehängt, die den gesamten HTML- und CSS-Code Vollständig kommentiert beinhaltet.

...Und Fertig!

zumindest mit dem Hauptteil, wer noch einen Regler einstellen möchte, der die Abspielgeschwindigkeit des ganzen steuert, kann hier weitermachen:


Die Animation geht mir zu schnell/ zu langsam!

Der Input-Tag ist super praktisch, da er auch kleine Javascript-Befehle direkt im Tag ausführen kann.

Um Herauszufinden, welches Bild angezeigt werden sollte, haben wir den Bildern bestimmte Scrollbereiche zugeordnet. Diese waren abhängig davon wie weit der User gescrollt hatte und auch wie hoch unser Dokument ist. Der Einfachste Weg diese Berechnung zu beeinflussen ist, die Dokumenthöhe zu ändern.

Fügen wir unserem HTML-code doch erstmal einen Schieberegler hinzu:

<input "type="range" id="regler" min="200" max="1500" value="900" step="50">

<!-- "type='range'", weil wir hier einen Schieberegler wollen, andere types, wie Eingabefelder etc. würden
auch funktionieren -->

Die Regler sehen bei jedem Browser anders aus, um Böse überraschungen zu vermeiden, kannst du hier schauen wie er bei dir aussieht:

Deswegen haben wir Inline-CSS

Der Grund dafür, warum wir einen Teil unseres CSS-codes im head stehen haben

Es ist logisch: Der Regler muss auf die Höhe von unserem Dokument zugreifen, dieser kann aber nicht in andere Text-Dateien hineinsehen, sondern nur innerhalb der eigenen Datei auf Werte zugreifen. Deshalb steht die Dokumentenhöhe im <Style> -Tag im head.

Feste Werte können wir nicht verändern

Aus diesem Grund nehmen wir ein paar änderungen an unserem style vor:

<!DOCTYPE html>
<html>
<head>   
    <meta charset="utf-8">
    
    <title>cooler Scrolleffekt</title>
    
    <link rel="stylesheet" href="style.css"> 

    <style> 
    
    :root {

        --hoch: 500vh;                        /* Dokumentenhöhe wird hier erstmal auf 500vh gelegt, 1vh    */
                                              /*   entspricht 1% der Viewporthöhe, bei diesem Wert ist die */
                                              /*   Animationsgeschwindigkeit "normal".                     */
        
        }
        
        html {
        
            height: var(--hoch);      
        }
                                     /* Zusätzlich zum externen Style-sheet hier ein inline-style, damit der Regler auf diesen Wert zugreifen kann */
        </style>
</head>

Statt einem festgesetzten Wert für die Höhe, nutzen wir eine Variable, die einfach veränderbar ist.

»Root« greift hier einfach auf das HTML-Dokument an sich zu, hier wird eine Variable deklariert und erstmal auf unsere normalen 500vh Höhe gelegt.

dann wird beim Html die Dokumentenhöhe auf den Wert der Variable gesetzt.

Vielleicht kann man jetzt schon erkennen, was der nächste Schritt ist.

Der Regler verstellt diese Variable.

Jackpot!

Den Input-Tag kann man mit einem Attribut namens »oninput« versehen, der, etwas geschehen lässt, sobald unser Regler einen Input erhält.

<input style ="direction: rtl; " type="range" id="regler" min="200" max="1500" value="900" step="50" oninput="document.documentElement.style.setProperty( '--hoch' ,  this.value +  'vh');">

<!-- min und max sind hier so festgelegt, dass es für unser Beispiel sinn ergibt, ihr könnt sie einstellen wie ihr wollt. 

Value ist der Wert, auf den der Regler beim Öffnen der Seite gesetzt wird

Step ist einfach die Schrittweite des Reglers-->

nach dem Gleichzeichen steht der Pfad, auf dem der Regler die Variable »--hoch« findet und was er damit machen soll, nämlich die Variable zu dem eingegebenen Wert (this.value) »vh« haben wir als Text dazu gesetzt damit es dann im Style-Tag vollständig mit Einheit steht.

Dank der Art unserer Berechnung der Bilder, wird die Animation beim Ziehen des Reglers nach rechts langsamer und nach links schneller. Da dies ein wenig konter-intuitiv ist, spiegeln wir den Regler mit dem Style-Attribut und sagen direction: rtl (»right to left«). Nun ist der Regler auch funktionsfähig und sinnvoll gerichtet.

Finishing Touches

kleine sachen zum rumspielen

Vorallem am Regler kann man mit den Werten ein wenig herumprobieren bzw. rechnen bis man ein Minimum und Maximum hat, das Sinn ergibt. Bei wenig Bildern empfiehlt es sich das Maximum nicht zu hoch zu machen, da die Animation sonst bei vollem Regler sofort vorbei ist. Sonst kann man noch Farben und Styles vom Regler und Hintergrund anpassen. Wenn alles so funktioniert, wie ihr es möchtet, seid ihr fertig und habt eine funktionierende scroll-gesteuerte Animation.

enjoy :)

Download:

Tutorial-Dateien herunterladen

Quellen:

CSS - Tricks
0t1 Style guide
w3schools

Schlagworte


© 0t1

Cookies

0t1 mag keine Kekse (und kein Tracking). Wir verwenden lediglich notwendige Cookies für essentielle Funktionen.

Wir verwenden Schriftarten von Adobe Fonts. Dafür stellt dein Browser eine Verbindung zu den Servern von Adobe in den USA her. Wenn du unsere Seite nutzen möchtest, musst du dich damit einverstanden erklären.

Weitere Informationen in unserer Datenschutzerklärung.