Vue.js Fullpage Scroll Komponente: Dynamisches Scrolling für deine Webseite
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:
Attribut | Wert | Beschreibung |
---|---|---|
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.
Navigation
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.
Wie fandest du diesen Beitrag?