Vue.js Fullpage Scroll Komponente: Dynamisches Scrolling für deine Webseite

Vue.js Fullpage Scroll Demo

In diesem Artikel erfährst du, wie du eine eigene Vue.js Fullpage Scroll Komponente für deine Vue.js App programmierst und deine Webseite mit einem dynamischen Scrolling aufwertest.

Fullpage Scroll bedeutet, dass man nicht normal scrollt, sondern man immer direkt von einer Section zur nächsten, bzw. zur vorherigen Section gescrollt wird. Deshalb zeige ich dir zuerst eine Demo zur Vue.js Fullpage Scroll Komponente.

Hübsche Vue.js Fullpage Demo

Damit direkt von Anfang an feststeht, wie das Vue.js Fullpage Scroll (oder OnePage Scroll) aussehen wird, habe ich hier schon mal eine Demo vorbereitet. Diese Version wird von allen gängigen modernen Browsern unterstützt und funktioniert auch auf mobilen Endgeräten.

Wenn du noch Design-Inspirationen suchst habe ich hier noch zwei Seiten, die den Fullpage Scroll meiner Meinung nach extrem gut in Szene gesetzt haben:

Warum keine fertige Vue.js Fullpage Scroll Komponente verwenden?

Das kannst du sehr gerne tun um dir Arbeit zu sparen. Die existierenden funktionieren super! Allerdings ist es doch viel cooler, das ganze selber zu programmieren, oder? 😉 Und außerdem hat man dann nicht so viele Funktionen auf seiner Seite, die man oft gar nicht benötigt.

Wenn du kein Freund von Vue.js bist, kannst du das ganze auch mit React, AngularJS oder jQuery umsetzen. Die Vorgehensweise ist meist sehr ähnlich. Einzelne Funktionen müssen natürlich an die Frameworks angepasst werden.

Falls du noch ein Neuling in Vue.js bist, kannst du diese Vue.js Beispiele programmieren, um deine Skills zu verbessern.

Schritt 1: HTML Gerüst erstellen

Zu erst benötigen wir einen Container, in dem unsere Vue.js App läuft. Dazu erstellen wir einen Container #app. Dort kommt das restliche HTML rein.

<div id="app">
    <!-- CONTENT HERE -->
</div>

Als nächstes legen wir unsere einzelnen Sections (Abschnitte) an. Dort kannst du dann beliebigen Inhalt reinpacken und gestalten.

<section class="fullpage">
    <h1>Section 1</h1>
</section>
<section class="fullpage">
    <h1>Section 2</h1>
</section>
<section class="fullpage">
    <h1>Section 3</h1>
</section>
<section class="fullpage">
    <h1>Section 4</h1>
</section>
<section class="fullpage">
    <h1>Section 5</h1>
</section>

Im nächsten Schritt wollen wir das seitlich Menü erstellen. Damit kann man per Klick in eine andere Section navigieren und bekommt immer die aktive Section angezeigt.

<div class="sections-menu">
  <span
     class="menu-point"
     v-bind:class="{active: activeSection == index}"
     v-on:click="scrollToSection(index)"
     v-for="(offset, index) in offsets"
     v-bind:key="index"
     v-title="'Go to section ' + (index+1)">
  </span>
</div>

Zu diesem Block benötigt es jetzt etwas Erklärung: Um das Menü machen wir ein Wrapper .sections-menu. Darin ist ein span-Tag, welcher einige Attribute für Vue.js enthält. Deshalb hier die genaue Erklärung:

AttributWertBeschreibung
v-bind:class {active: activeSection == index} Der Tag bekommt die Klasse active, wenn der aktuelle Schleifendurchlauf gleich der aktiven Section ist.
v-on:click scrollToSection(index) Beim Klick auf den Link wird die Funktion scrollToSection() aufgerufen. Der Parameter ist der Schleifendurch und somit unsere Section ID.
v-for (offset, index) in offsets Der Link wird nach Anzahl der Elemente im offsets Array wiederholt. Die Variable index ist stellt unsere Section ID dar.
v-bind:key index Um jeden Schleifen Durchlauf eindeutig zu halten, setzen wir unsere Section ID als key für die for-Direktive.
v-title‚Go to section ‚ + (index+1)Setzt einen Titel beim Hovern mit der Nummer der Section

Schritt 2: Sections stylen (CSS)

Damit der Effekt des Fullpage Scrolls richtig zur Geltung kommt, sollten die einzelnen Sections mindestens 100vh (also genau Bildschirmhöhe) betragen. Du musst also sehen, dass der Inhalt einer Section auf genau diesen Platz angepasst ist.

.fullpage {
  height: 100vh;
  width: 100%;
}

In unserem Beispiel haben wir lediglich eine Überschrift und Unterüberschrift. Für Inspirationen schau dir doch mal die oben verlinkten Demos an.

Das Menü zum Navigieren habe ich auch möglichst einfach gehalten. Weiße Punkte, bei denen der aktive Punkt stärker und größer ist. Außerdem sitzt das Menü immer an der rechten Seite des Bildschirmrandes. Das CSS dazu sieht so aus:

.sections-menu {
  position: fixed;
  right: 1rem;
  top: 50%;
  transform: translateY(-50%);
}

.sections-menu .menu-point {
  width: 10px;
  height: 10px;
  background-color: #FFF;
  display: block;
  margin: 1rem 0;
  opacity: .6;
  transition: .4s ease all;
  cursor: pointer;
}

.sections-menu .menu-point.active {
  opacity: 1;
  transform: scale(1.5);
}

.sections-menu .menu-point:hover {
  opacity: 1;
  transform: scale(1.2);
}

CSS zum Positionieren der Schrift, etc. habe ich hier nicht behandelt, da es sich um Basics handelt und nichts mit dem eigentlichen Feature zu tun hat. Den kompletten Code findest du auf meinem Pen auf Codepen.

Schritt 3: Funktionalitäten in Vue.js/JavaScript programmieren

Das JavaScript ist hier die aufwendigste Sache gewesen. Wir müssen sowohl alle modernen Browser, als auch Mobilgeräte abdecken.

Vue.js App initialisieren

Wir beginnen mit dem Initialisieren der Vue.js App. Dazu haben wir bereits im HTML den #app Container angelegt.

var app = new Vue({
  el: '#app',
});

Variablen deklarieren und initialisieren

Nun deklarieren und initialisieren wir die Variablen. Später wird deutlich für das wir welche Variable benötigen, falls der Name das nicht schon verrät.

data: {
    inMove: false,
    inMoveDelay: 400,
    activeSection: 0,
    offsets: [],
    touchStartY: 0
}

Offsets berechnen

Nun wollen wir die Offsets (obere Kante der Abschnitte) der einzelnen Sections berechnen. Das bringt uns den Vorteil, dass wir uns Rechenleistung sparen, da wir das nicht bei jedem Scroll neu berechnen müssen.

Wir laufen mit einer Schleife über alle section Element drüber und speichern uns den Offset in unserem globale offsets Array.

calculateSectionOffsets() {
    let sections = document.getElementsByTagName('section');
    let length = sections.length;

    for (let i = 0; i < length; i++) {
        let sectionOffset = sections[i].offsetTop;
        this.offsets.push(sectionOffset);
    }
}

Die Funktion wird einmal beim Erstellen der Applikation in der mounted() Funktion aufgerufen.

mounted() {
    this.calculateSectionOffsets();
}

Event Listener

Wir benötigen einige Event Listener, um die Scroll Bewegung für Desktop und den Swipe auf Mobilgeräten abzufangen. Dabei registrieren wir diese Listener in der mounted() Funktion.

window.addEventListener('DOMMouseScroll', this.handleMouseWheelDOM); // Mozilla Firefox
window.addEventListener('mousewheel', this.handleMouseWheel, {
    passive: false
}); // Other browsers

window.addEventListener('touchstart', this.touchStart, {
    passive: false
}); // mobile devices
window.addEventListener('touchmove', this.touchMove, {
    passive: false
}); // mobile devices

Außerdem entfernen wir die Event Listener beim Beenden der Anwendung in der destroyed() Funktion wieder.

destroyed() {
    window.removeEventListener('mousewheel', this.handleMouseWheel, {
        passive: false
    }); // Other browsers
    window.removeEventListener('DOMMouseScroll', this.handleMouseWheelDOM); // Mozilla Firefox

    window.removeEventListener('touchstart', this.touchStart); // mobile devices
    window.removeEventListener('touchmove', this.touchMove); // mobile devices
}

Wie du schon an den Kommentare sehen kannst, gibt es für verschiedene Browser unterschiedliche Events. Bei manchen wird der Parameter passive: false mitgegeben. Dieser muss unbedingt eingefügt werden.

Ich habe viel rum probiert, bis das Scrollen flüssig funktioniert hat. Das Ergebnis konnte ich nur mit diesem Parameter erzielen. Außerdem wurden sonst Fehlermeldungen in der Browser Console angezeigt.

Scroll Funktion

Diese Funktion wird bereits von unseren HTML Links aufgerufen. Hiermit scrollen wir zu der Section. Der Parameter id ist dabei die Section ID. Die Variable inMove sorgt dafür, dass wir einen kleinen Cooldown haben. Über die Variable inMoveDelay können wir einstellen, wie lange dieser Cooldown sein soll. 400ms (also 0,4 Sekunden) sind hier ein recht guter Wert, ist aber geschmackssache. Mit dem Parameter force auf true können wir den Cooldown überspringen.

scrollToSection(id, force = false) {
    if (this.inMove && !force) return false;

    this.activeSection = id;
    this.inMove = true;

    document.getElementsByTagName('section')[id].scrollIntoView({
        behavior: 'smooth'
    });

    setTimeout(() => {
        this.inMove = false;
    }, this.inMoveDelay);
},

Scroll Richtung erkennen

Die Funktion handleMouseWheel ist der Event Listener des Scroll Events auf Desktop Geräten (mousewheel & DOMMouseScroll).

Über die Variable wheelDelta des Events können wir erkennen, ob der Nutzer hoch oder runter scrollt. Dementsprechend wird unsere moveUp() oder moveDown() Funktion aufgerufen, die im nächsten Schritt erstellt wird. Am Ende wird durch e.preventDefault() und return false; das Event abgebrochen.

handleMouseWheel: function(e) {

    if (e.wheelDelta < 30 && !this.inMove) {
        this.moveUp();
    } else if (e.wheelDelta > 30 && !this.inMove) {
        this.moveDown();
    }

    e.preventDefault();
    return false;
},

Section hoch- und runter scrollen

Diese beiden Funktionen sind nur dafür zuständig, einmal hoch- oder runter zu scrollen. Wenn wir runter scrollen und die Section kleiner als 0 wäre, scrollen wir zu der letzten Section. Anders herum ist es, wenn die neue Section größer als die Anzahl der Sections wäre, scrollen wir zur ersten Section. 0 ist dabei die ersten Section.

moveDown() {
    this.inMove = true;
    this.activeSection--;

    if (this.activeSection < 0) this.activeSection = this.offsets.length - 1;

    this.scrollToSection(this.activeSection, true);
},
moveUp() {
    this.inMove = true;
    this.activeSection++;

    if (this.activeSection > this.offsets.length - 1) this.activeSection = 0;

    this.scrollToSection(this.activeSection, true);
}

Damit haben wir ein Endlos Scroll geschaffen. Wenn du das nicht möchtest, kannst du einfach keinen Swipe ausführen, sodass der Nutzer an den Enden nur in die andere Richtung scrollen kann.

Mobile Swipe erkennen

Mobil haben wir die Events touchstart und touchmove, durch die wir erkennen können, wohin der Nutzer scrollt. Wenn der Nutzer anfängt zu scrollen wird touchStart() aufgerufen. Dort speichern wir uns die Y Position. Wenn der Nutzer dann seinen Finger auf dem Display bewegt, wird touchMove() aufgerufen.

Diese beiden Werte vergleichen wir dann und sehen, ob der Nutzer hoch oder runter scrollt. Dementsprechend wird unsere moveUp() oder moveDown() Funktion aufgerufen, die wir zuvor erstellt haben.

touchStart(e) {
    e.preventDefault();

    this.touchStartY = e.touches[0].clientY;
},
touchMove(e) {
    if (this.inMove) return false;
    e.preventDefault();

    const currentY = e.touches[0].clientY;

    if (this.touchStartY < currentY) {
        this.moveDown();
    } else {
        this.moveUp();
    }

    this.touchStartY = 0;
    return false;
}

Fazit

Wie du siehst kannst du deine eigenen Features hinzufügen oder Teile entfernen, wenn sie dir nicht gefallen. Ein Vue.js Fullpage Scroll ist ein sehr schickes Feature und bei richtiger Benutzung kannst du sehr schöne Ergebnisse zaubern.

Wusstest du, dass du Vue.js auch ohne Build-Tools, etc. nutzen kannst? Nein, dann schau dir doch meinen Artikel zum Thema Vue ohne Node oder CLI an.

Ähnliche Beiträge
Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

bold italic underline strikeThrough
insertOrderedList insertUnorderedList outdent indent
removeFormat
createLink unlink
code

Das könnte dich auch interessieren