Tauchen Sie ein in die faszinierende Welt der Animation mit GSAP (GreenSock Animation Platform). Erleben Sie die Magie fließender Bewegungen, atemberaubender Effekte und dynamischer Interaktionen. Mit GSAP können Sie Ihre Website zum Leben erwecken und Ihren Benutzern ein unvergessliches Erlebnis bieten. Entdecken Sie die grenzenlosen Möglichkeiten von GSAP und lassen Sie Ihrer Kreativität freien Lauf!
EINLEITUNG
Den Onepager mit GSAP erweitern
Im dritten Teil erweitern wir unseren Onepager um zusätzliche Animationen und Interaktionen. Nachdem die grundlegende Seitenstruktur, die CSS-Effekte und die ersten JavaScript-Funktionen bereits stehen, kommt nun GSAP (GreenSock Animation Platform) zum Einsatz.
Mit GSAP können wir Animationen präzise steuern und sie beispielsweise direkt mit der Scrollposition oder der Bewegung des Mauszeigers verbinden. Zusätzlich verwenden wir die Plugins ScrollTrigger und ScrollToPlugin.
Damit erstellen wir im weiteren Verlauf unter anderem Texteffekte beim Scrollen, magnetische Elemente und einen kreisförmigen Effekt, der dem Mauszeiger folgt. Außerdem machen wir innerhalb dieses Kreises zusätzliche Inhalte sichtbar und passen die Bedienung später für mobile Geräte an.
Zunächst binden wir GSAP und die benötigten Plugins in unsere index.html ein:
GSAP selbst bildet die Grundlage für unsere Animationen. ScrollTrigger ermöglicht es uns, Animationen abhängig von der Scrollposition auszuführen. ScrollToPlugin erweitert GSAP um Funktionen zum animierten Scrollen zu bestimmten Positionen innerhalb der Seite.
Damit ist die Grundlage geschaffen. Als ersten Effekt lassen wir im nächsten Schritt unsere Texte beim Scrollen sichtbar werden.
TEXTEFFEKT
Text beim Scrollen sichtbar machen
Als ersten GSAP-Effekt animieren wir unsere Texte abhängig von der Scrollposition. Der Text ist zunächst nur schwach sichtbar und wird beim Scrollen nach und nach vollständig hervorgehoben.
Die dafür benötigten Farben haben wir bereits als CSS-Variablen in :root definiert. Entscheidend ist hier --color-text-transparent:
Mit einem Alpha-Wert von 0.2 ist die Farbe nur zu 20 Prozent deckend. Dadurch können wir den Text zunächst zurückhaltend darstellen und ihn anschließend über die bereits vorhandene Hintergrunddarstellung hervorheben.
Für die eigentliche Scrollanimation ergänzen wir unsere assets/scripts.js:
Zunächst registrieren wir mit gsap.registerPlugin(ScrollTrigger) das zuvor eingebundene ScrollTrigger-Plugin.
Anschließend sammelt gsap.utils.toArray(".text") alle Elemente mit der Klasse .text. Für jedes dieser Elemente erzeugen wir eine eigene GSAP-Animation.
Dabei wird backgroundSize während des Scrollens bis auf 100% vergrößert. Die eigentliche Textdarstellung haben wir bereits im ersten Teil über background-clip: text vorbereitet.
ScrollTrigger legt fest, wann die Animation beginnt und endet. Mit
start: "center 70%",
end: "center 30%",
beginnt die Animation, wenn sich die Mitte des jeweiligen Textelements auf Höhe von 70 Prozent des Viewports befindet. Sie endet, wenn die Mitte des Elements die 30-Prozent-Position erreicht.
Durch
scrub: true
ist die Animation direkt an die Scrollbewegung gekoppelt. Scrollen wir vor oder zurück, bewegt sich auch die Animation entsprechend mit.
31.mp4
17.8 MB
MAGNETISCHER EFFEKT
Elemente auf die Mausbewegung reagieren lassen
Im nächsten Schritt erstellen wir einen magnetischen Effekt für ausgewählte Elemente. Bewegen wir den Mauszeiger über ein solches Element, verschiebt es sich leicht in Richtung des Mauszeigers. Verlässt die Maus den Bereich wieder, bewegt sich das Element sanft zurück an seine ursprüngliche Position.
Welche Elemente auf diesen Effekt reagieren sollen, bestimmen wir über die bereits verwendete Klasse .magnetic. Unser Logo aus dem ersten Teil besitzt diese Klasse beispielsweise schon:
Zunächst wählen wir mit document.querySelectorAll(".magnetic") alle Elemente aus, die auf die Mausbewegung reagieren sollen. Über strength bestimmen wir anschließend die Stärke der Bewegung.
Für jedes dieser Elemente registrieren wir zwei Ereignisse. mousemove wird ausgeführt, solange sich der Mauszeiger über dem Element bewegt. Dabei ruft der Event-Listener die Funktion moveMagnet() auf.
Mit getBoundingClientRect() ermitteln wir die aktuelle Position und Größe des Elements. Anschließend berechnen wir aus der Position des Mauszeigers, wie weit sich das Element horizontal und vertikal bewegen soll.
Befindet sich der Mauszeiger beispielsweise rechts von der Mitte, erhält das Element einen positiven X-Wert. Befindet er sich links davon, wird der Wert negativ. Dasselbe Prinzip verwenden wir für die vertikale Bewegung.
Die Bewegung selbst wird mit gsap.to() animiert. Über duration: 1 legen wir eine Animationsdauer von einer Sekunde fest. ease: "power4.out" sorgt dafür, dass die Bewegung zum Ende hin weich abbremst.
Sobald der Mauszeiger das Element verlässt, animieren wir x und y wieder auf 0. Dadurch bewegt sich das Element sanft zurück an seine ursprüngliche Position.
32.mp4
3.48 MB
KREISMASKE
Einen Kreis für die versteckten Inhalte vorbereiten
Als Nächstes erstellen wir die Grundlage für einen weiteren visuellen Effekt. Ein zusätzlicher Inhaltsbereich wird zunächst ausgeblendet und später über eine kreisförmige Maske sichtbar gemacht. Die Position und Größe dieses Kreises können wir anschließend mit GSAP steuern.
Zunächst ergänzen wir dafür die benötigten Styles:
Die drei CSS-Variablen --x, --y und --size bilden die Grundlage der Kreisbewegung. --x und --y bestimmen die Position des Kreises, während --size seinen Radius festlegt.
Die eigentliche Maske entsteht über einen radialen Verlauf:
--mask: radial-gradient(
circle at var(--x) var(--y),
black var(--size),
transparent 0
);
Der schwarze Bereich der Maske macht den entsprechenden Teil des Elements sichtbar, während der transparente Bereich ausgeblendet bleibt. Über mask-image beziehungsweise -webkit-mask-image wenden wir diese Maske auf .hidden-content an.
Mit pointer-events: none stellen wir sicher, dass der zusätzliche Inhaltsbereich keine Mausereignisse abfängt. Links und andere interaktive Elemente der eigentlichen Seite bleiben dadurch weiterhin erreichbar.
Zu Beginn ist .hidden-content ausgeblendet. Sobald später die Klasse .active hinzugefügt wird, können wir den Bereich anzeigen und die Kreisgröße sowie seine Position mit GSAP verändern.
Nun ergänzen wir innerhalb unseres <main>-Bereichs hinter .content und vor dem <aside> zunächst den Container für den versteckten Inhalt:
Dieser Container bleibt zunächst leer. Im weiteren Verlauf füllen wir ihn mit einer zweiten Inhaltsebene, die durch unsere Kreis-Maske sichtbar wird.
KREIS ANIMIEREN
Die Maske der Maus folgen lassen
Nachdem wir die kreisförmige Maske mit CSS vorbereitet haben, steuern wir sie nun mit GSAP. Der Kreis soll sich an der Position des Mauszeigers befinden und größer werden, sobald wir mit der Maus über einen unserer Inhaltsbereiche fahren.
Zunächst holen wir uns Referenzen auf den versteckten Inhaltsbereich und den normalen .content-Bereich. Die CSS-Variablen --x und --y, die wir zuvor für unsere Maske angelegt haben, können anschließend direkt über GSAP verändert werden.
Mit gsap.quickSetter() erstellen wir Funktionen, mit denen sich diese Werte besonders effizient aktualisieren lassen:
Zusätzlich verwenden wir gsap.quickTo(). Dadurch bewegt sich die Maske nicht abrupt von einer Position zur nächsten, sondern folgt der Maus mit einer weichen Animation:
ease: "power4.out"
Anschließend erstellen wir eine pausierte GSAP-Timeline. Sie verändert --size auf 250 und vergrößert damit den sichtbaren Bereich unserer radialen Maske.
Auf kleineren Displays wird zusätzlich display: "block" gesetzt. Die spezielle Bedienung für mobile Geräte ergänzen wir später noch separat.
Mit
gsap.utils.toArray(".display", content);
sammeln wir alle .display-Elemente innerhalb unseres normalen Inhaltsbereichs. Betritt der Mauszeiger einen solchen Bereich, starten wir die Timeline mit tl.restart(). Verlässt er ihn wieder, läuft sie mit tl.reverse() rückwärts und der Kreis wird wieder kleiner.
Beim ersten mousemove positionieren wir die Maske an der aktuellen Mausposition und machen den versteckten Bereich über autoAlpha sichtbar. Anschließend aktualisieren xTo() und yTo() die Position bei weiteren Mausbewegungen.
Zum Schluss reagieren wir auf das Betreten und Verlassen des normalen .content-Bereichs. Dabei wird die Klasse .active am direkt folgenden .hidden-content ein- beziehungsweise ausgeschaltet. Diese Klasse haben wir im vorherigen CSS-Abschnitt bereits vorbereitet.
Damit besitzen wir nun einen kreisförmigen Bereich, dessen Position von der Maus gesteuert wird und dessen Größe sich beim Überfahren unserer Inhalte animiert.
31.webp
119 KB
KREISBEWEGUNG
Den Kreis beim Scrollen und Bewegen der Maus aktualisieren
Unsere Maske reagiert bereits auf die Mausbewegung. Beim Scrollen der Seite müssen wir ihre Position jedoch ebenfalls aktualisieren, damit der Kreis weiterhin an der richtigen Stelle zum Mauszeiger dargestellt wird.
Dafür ergänzen wir den folgenden Code in unserer assets/scripts.js:
Bei jeder Mausbewegung speichern wir zunächst die aktuelle Position des Mauszeigers:
mouse.x = e.clientX;
mouse.y = e.clientY;
clientX und clientY liefern die Position innerhalb des aktuell sichtbaren Browserfensters. Da sich unsere Seite jedoch auch scrollen lässt, berücksichtigen wir zusätzlich window.scrollX und window.scrollY.
Beim Scrollen berechnen wir deshalb die Position des Mauszeigers innerhalb des gesamten Dokuments neu:
gsap.ticker.deltaRatio() berücksichtigt die tatsächlich vergangene Zeit zwischen den einzelnen Aktualisierungen. Zusammen mit unserem zuvor definierten speed-Wert erhalten wir damit einen Wert, mit dem die Scrollbewegung angepasst wird.
Die Abfrage
if (!linkAnimated)
verhindert außerdem, dass die Position der Maske durch diese Event-Listener verändert wird, während ein anderer Effekt die Kontrolle über den Kreis übernommen hat. Diese Funktion benötigen wir später noch einmal.
Damit kann die Position der Kreis-Maske sowohl auf Mausbewegungen als auch auf das Scrollen der Seite reagieren.
33.mp4
12.8 MB
VERSTECKTER INHALT
Text innerhalb des Kreises sichtbar machen
Bisher ist unser .hidden-content noch leer. Die Kreis-Maske funktioniert bereits, innerhalb des sichtbaren Bereichs gibt es aber noch keinen eigentlichen Inhalt.
Jetzt ergänzen wir eine zweite Variante unseres Hero-Bereichs innerhalb von #hiddenContents. Dieser Inhalt wird nur dort sichtbar, wo unsere kreisförmige Maske die versteckte Ebene freigibt.
Die Struktur entspricht unserem bereits vorhandenen Hero-Bereich. Der entscheidende Unterschied ist, dass sich diese Variante innerhalb von .hidden-content befindet.
Dadurch liegen zwei Inhaltsebenen übereinander: Die normale Seite bleibt sichtbar und die versteckte Ebene wird nur innerhalb unserer beweglichen Kreis-Maske freigegeben.
Für die hervorgehobenen Wörter ergänzen wir außerdem noch eine kleine CSS-Regel:
Die Regel gilt ausschließlich für <strong>-Elemente innerhalb von .hidden-content. Dadurch können wir einzelne Wörter auf der versteckten Ebene besonders kräftig und dunkel darstellen, ohne die <strong>-Elemente der übrigen Seite zu verändern.
Bewegen wir nun den Kreis über den Hero-Bereich, erscheint innerhalb der Maske der alternative Inhalt der versteckten Ebene.
33.mp4
12.8 MB
ABOUT ME
Die versteckte Ebene für den nächsten Bereich ergänzen
Nachdem wir den alternativen Hero-Bereich in unsere versteckte Ebene eingefügt haben, erweitern wir diese nun passend zum nächsten Abschnitt unserer normalen Seite.
Innerhalb von #hiddenContents fügen wir direkt nach dem versteckten Hero-Bereich den folgenden Abschnitt ein:
// index.html
<!-- ------------------------------ About me ------------------------------- --><divclass="row justify-content-center align-items-center min-vh-100"><divclass="display width-100"><pclass="about_content_label">About me</p><divclass="display-hidden">
Ein visueller Designer - mit Fähigkeiten
</div><divclass="display-hidden">
die noch nicht von KI ersetzt wurden - der nur gute Arbeit macht,
</div><divclass="display-hidden">wenn das Gehalt ebenso gut ist.</div></div></div><!-- ---------------------------- About me ende ---------------------------- -->
Die bereits vorhandenen Hilfsklassen row, justify-content-center, align-items-center und min-vh-100 sorgen dafür, dass sich auch dieser versteckte Bereich an der Struktur des entsprechenden sichtbaren Abschnitts orientiert.
Für die Texte verwenden wir die neue Klasse .display-hidden. Diese gestalten wir nun in unserer assets/styles.css:
Auf kleineren Displays verwenden wir zunächst eine Schriftgröße von 2rem und seitliche Abstände von jeweils 1rem.
Ab einer Breite von 1248px wird die Schriftgröße mit 4vw abhängig von der Breite des Browserfensters berechnet. Gleichzeitig entfernen wir die zusätzlichen seitlichen Innenabstände.
Durch max-width: 1248px bleibt der Textbereich auf großen Bildschirmen begrenzt, während margin: auto ihn innerhalb der verfügbaren Breite zentriert.
Damit besitzt nun auch der About-me-Bereich einen eigenen Inhalt auf der versteckten Ebene, der innerhalb unserer beweglichen Kreis-Maske sichtbar werden kann.
WHAT I DO
Einen leeren Bereich in der versteckten Ebene anlegen
Auch der nächste Bereich unserer normalen Seite benötigt ein entsprechendes Gegenstück innerhalb von #hiddenContents.
Für What I Do benötigen wir allerdings keinen zusätzlichen Text. Stattdessen legen wir lediglich einen leeren Bereich mit derselben Höhe wie der sichtbare Abschnitt an.
Direkt nach unserem versteckten About-me-Bereich ergänzen wir:
// index.html
<!-- ----------------------------- what i do ------------------------------- --><divclass="row justify-content-center align-items-center min-vh-100"></div><!-- ----------------------------- ende what i do -------------------------- -->
Obwohl dieser Bereich keinen eigenen Inhalt enthält, ist er für den Aufbau unserer versteckten Ebene wichtig.
Die Klasse min-vh-100 sorgt dafür, dass der Bereich mindestens die Höhe des Browserfensters einnimmt. Dadurch bleibt die vertikale Struktur der versteckten Ebene an dieser Stelle erhalten.
Da wir innerhalb der Kreis-Maske für What I Do keinen alternativen Inhalt anzeigen möchten, bleibt das Element bewusst leer.
Auf diese Weise folgt der nächste versteckte Abschnitt wieder an der passenden Position.
EXPERIENCE
Den versteckten Inhalt für Experience ergänzen
Nach dem leeren Bereich für What I Do folgt der Abschnitt Experience. Auch für diesen Bereich erstellen wir wieder eine alternative Textebene, die innerhalb unserer Kreis-Maske sichtbar wird.
Direkt nach dem leeren What-I-Do-Bereich ergänzen wir innerhalb von #hiddenContents:
// index.html
<!-- ----------------------------- experience ------------------------------ --><divclass="row justify-content-center align-items-center min-vh-100"><divclass="display"><pclass="about_content_label">Experience</p><divclass="display-hidden">
Nur sieben Jahre lang habe ich aktiv
</div><divclass="display-hidden">
coole Sachen produziert. Die anderen Jahre
</div><divclass="display-hidden">waren eher ein Herumprobieren und</div><divclass="display-hidden">Durchlaufen meiner Karriere.</div></div></div><!-- --------------------------- experience ende --------------------------- -->
Wie schon beim About-me-Bereich verwenden wir für die einzelnen Textzeilen die Klasse .display-hidden.
Die dafür benötigten Styles haben wir bereits im vorherigen Abschnitt angelegt. Deshalb müssen wir für Experience kein zusätzliches CSS hinzufügen.
erhält auch dieser Abschnitt wieder die entsprechende Höhe und Ausrichtung innerhalb der versteckten Ebene.
Der eigentliche Text befindet sich in einem .display-Element. Diese Klasse ist außerdem für unsere zuvor erstellte GSAP-Timeline wichtig: Beim Überfahren der entsprechenden .display-Bereiche wird die Kreis-Maske vergrößert beziehungsweise wieder verkleinert.
Die einzelnen .display-hidden-Elemente übernehmen das bereits festgelegte responsive Schriftbild. Auf kleineren Displays verwenden sie eine feste Schriftgröße, während die Schrift auf größeren Bildschirmen proportional zur Breite des Browserfensters skaliert.
Damit besitzt nun auch der Experience-Bereich seine eigene versteckte Textebene.
HISTORY
Einen leeren Bereich für History anlegen
Nach Experience folgt auf unserer normalen Seite der Bereich History. Auch hier benötigen wir innerhalb der versteckten Ebene keinen zusätzlichen Text.
Damit die vertikale Struktur von #hiddenContents weiterhin mit der sichtbaren Seite übereinstimmt, legen wir wieder einen leeren Bereich mit mindestens der Höhe des Browserfensters an.
Direkt nach dem versteckten Experience-Bereich ergänzen wir:
// index.html
<!-- ------------------------------- history ------------------------------- --><divclass="row justify-content-center align-items-center min-vh-100"></div><!-- ---------------------------- history ende ----------------------------- -->
Wie bereits bei What I Do dient dieses leere Element als Platzhalter innerhalb unserer versteckten Ebene.
Die Klasse min-vh-100 sorgt dafür, dass der Abschnitt mindestens die Höhe des Browserfensters einnimmt. Dadurch bleibt die Reihenfolge und vertikale Aufteilung der versteckten Inhalte erhalten, obwohl wir für History keinen alternativen Text anzeigen.
Innerhalb der Kreis-Maske bleibt dieser Abschnitt daher inhaltlich leer. Erst beim darauffolgenden Bereich fügen wir wieder einen sichtbaren Inhalt zur versteckten Ebene hinzu.
CLIENTS
Den versteckten Inhalt für Clients ergänzen
Nach dem leeren History-Bereich folgt der Abschnitt Clients. Hier möchten wir innerhalb unserer Kreis-Maske wieder einen alternativen Text anzeigen.
Dazu ergänzen wir innerhalb von #hiddenContents direkt nach dem History-Bereich:
// index.html
<!-- ------------------------------- Clients ------------------------------- --><divclass="row justify-content-center align-items-center min-vh-100"><divclass="display"><pclass="about_content_label">Clients</p><divclass="display-hidden">
Ich war nur ein kleiner Teil eines großen
</div><divclass="display-hidden">
Teams. Sie haben wahrscheinlich keine
</div><divclass="display-hidden">Ahnung, dass ich existiere.</div></div></div><!-- ---------------------------- Clients ende ----------------------------- -->
Auch hier verwenden wir wieder .display als umschließendes Element und .display-hidden für die einzelnen Textzeilen.
Die Gestaltung von .display-hidden haben wir bereits beim About-me-Bereich festgelegt. Deshalb benötigen wir für diesen Abschnitt kein zusätzliches CSS.
Durch die Klasse .display reagiert der Bereich außerdem auf unsere zuvor eingerichtete GSAP-Timeline. Bewegt sich der Mauszeiger über den entsprechenden Inhaltsbereich, kann die Kreis-Maske vergrößert und der alternative Clients-Text innerhalb der versteckten Ebene sichtbar gemacht werden.
Die Kombination aus sichtbarer und versteckter Ebene bleibt damit auch in diesem Abschnitt erhalten.
CLIENTS-AUFZÄHLUNG
Einen leeren Bereich für die Kundenliste anlegen
Direkt nach unserem Clients-Bereich folgt auf der normalen Seite die Aufzählung der einzelnen Kunden. Für diesen Bereich möchten wir innerhalb der Kreis-Maske keinen zusätzlichen Inhalt anzeigen.
Damit die versteckte Ebene trotzdem dieselbe vertikale Struktur wie die normale Seite behält, ergänzen wir innerhalb von #hiddenContents einen weiteren leeren Bereich:
Wie bei den zuvor angelegten leeren Bereichen für What I Do und History dient dieses Element als Platzhalter.
Mit min-vh-100 erhält der Bereich mindestens die Höhe des Browserfensters. Dadurch bleibt innerhalb von #hiddenContents der notwendige Platz für die Clients-Aufzählung erhalten, obwohl dort kein alternativer Text dargestellt wird.
Die Kreis-Maske kann diesen Abschnitt somit passieren, ohne dass auf der versteckten Ebene zusätzlicher Inhalt erscheint. Der darauffolgende versteckte Bereich befindet sich anschließend wieder an der vorgesehenen vertikalen Position.
MOTTO
Den letzten versteckten Inhaltsbereich ergänzen
Zum Abschluss unserer versteckten Ebene ergänzen wir noch den Bereich Motto. Anders als bei den zuvor angelegten leeren Platzhaltern enthält dieser Abschnitt wieder eigenen Text, der innerhalb unserer Kreis-Maske sichtbar wird.
Direkt nach der leeren Clients-Aufzählung fügen wir innerhalb von #hiddenContents folgenden HTML-Code ein:
Wie bereits beim versteckten Hero-Bereich verwenden wir hier die vorhandenen Klassen text-center und text-black, um den Text mittig auszurichten und auf der farbigen versteckten Ebene dunkel darzustellen.
Die beiden Absätze mit .about_content_label bilden den oberen und unteren Abschluss des Bereichs. Mit .text-align-center werden auch diese Beschriftungen zentriert.
Der gesamte Inhalt befindet sich wiederum innerhalb eines .display-Elements. Dadurch wird auch dieser Bereich von unserer bereits eingerichteten Kreis-Animation berücksichtigt.
Zusätzliches CSS benötigen wir an dieser Stelle nicht, da wir ausschließlich Klassen verwenden, die bereits in unserem Stylesheet vorhanden sind.
Damit haben wir die versteckte Ebene für die einzelnen Bereiche unseres Onepagers aufgebaut. Sie folgt der Struktur der normalen Seite und kann über unsere kreisförmige Maske Stück für Stück sichtbar gemacht werden.
34.mp4
43.4 MB
KREIS AUSBLENDEN
Die Kreis-Maske über bestimmten Elementen ausblenden
Unsere Kreis-Maske folgt inzwischen dem Mauszeiger und macht die alternative Inhaltsebene sichtbar. Bei bestimmten Elementen möchten wir diesen Effekt jedoch vorübergehend deaktivieren.
Dafür verwenden wir die bereits vorhandene Klasse .hidden-link. Sobald sich der Mauszeiger über einem solchen Element befindet, blenden wir die versteckte Ebene aus. Verlässt der Mauszeiger das Element wieder, wird sie erneut sichtbar.
alle Elemente, bei denen die Kreis-Maske vorübergehend verschwinden soll.
Beim Betreten eines solchen Elements setzen wir:
linkAnimated = true;
Diese Variable haben wir bereits beim Erstellen unserer Kreissteuerung angelegt. Solange sie true ist, verhindern die dort eingebauten Abfragen, dass andere Maus- oder Scroll-Ereignisse gleichzeitig die Position der Maske verändern.
Anschließend setzen wir mit:
autoAlpha: 0
die versteckte Ebene unsichtbar. autoAlpha ist eine GSAP-Eigenschaft, die sowohl die Deckkraft als auch die Sichtbarkeit des Elements steuert.
Die aktuelle Mausposition speichern wir gleichzeitig wieder in den CSS-Variablen --x und --y.
Verlässt der Mauszeiger das .hidden-link-Element, setzen wir linkAnimated wieder auf false. Die normale Steuerung des Kreises kann damit wieder übernehmen.
Anschließend setzen wir die Transformation des versteckten Bereichs zurück und machen ihn mit
autoAlpha: 1
wieder sichtbar. Gleichzeitig wird die Kreis-Maske an der aktuellen Position des Mauszeigers eingeblendet.
Damit können wir einzelne Bereiche oder Links von unserem Kreis-Effekt ausnehmen, ohne die eigentliche Kreissteuerung zu deaktivieren.
KREISPOSITION KORRIGIEREN
Beim Wechsel von Scrollen zu Mausbewegung die Position übernehmen
Wenn wir durch die Seite scrollen und anschließend die Maus bewegen, soll die Kreis-Maske nicht plötzlich von einer falschen Position aus erscheinen. Deshalb passen wir die Funktion onFirstMove() an.
Die bisherige Funktion onFirstMove() wird dabei vollständig ersetzt. Wir fügen also keine zweite Funktion mit demselben Namen hinzu.
Für die Position innerhalb des sichtbaren Browserfensters verwenden wir jetzt clientX und clientY. Diese Koordinaten beziehen sich auf den Viewport und können deshalb sinnvoll mit window.innerWidth und window.innerHeight begrenzt werden.
Anschließend addieren wir die aktuelle Scrollposition:
Für alle weiteren Mausbewegungen verwenden wir die separate Funktion moveCircle().
Auch dort kombinieren wir die Mausposition innerhalb des Browserfensters mit der aktuellen Scrollposition. Dadurch bleibt die Position der Maske auch dann korrekt, wenn die Seite zuvor gescrollt wurde.
Zusätzlich berücksichtigen wir weiterhin unsere Variable linkAnimated:
if (linkAnimated) {
return;
}
Ist ein Bereich aktiv, bei dem wir den Kreis vorübergehend ausblenden, beendet die Funktion ihre Ausführung und verändert die Position der Maske nicht.
Damit kann der Wechsel zwischen Scrollen und Mausbewegung erfolgen, ohne dass die Kreis-Maske durch unterschiedliche Koordinatensysteme an eine falsche Position springt.
35.mp4
50.6 MB
Mobile Ansicht
Den Kreis-Effekt für Touch-Geräte vorbereiten
Unser bisheriger Kreis-Effekt wird mit Mausbewegungen gesteuert. Auf Smartphones und kleineren Tablets steht diese Art der Bedienung jedoch nicht zur Verfügung. Deshalb unterscheiden wir im nächsten Schritt zwischen der Desktop- und der mobilen Ansicht.
Dafür erstellen wir zunächst eine kleine Hilfsfunktion in unserer assets/scripts.js:
Die Funktion prüft die aktuelle Breite des Browserfensters. Unterhalb von 1248px behandeln wir die Darstellung für unseren Effekt als mobile Ansicht.
Damit verhindern wir anschließend, dass der mousemove-Listener für die erstmalige Aktivierung des Kreises auf diesen kleineren Ansichten registriert wird.
if (!isMobileDevice()) {
window.addEventListener("mousemove", onFirstMove);
}
Auf einer Desktop-Ansicht ab 1248px funktioniert unser bisheriger Maus-Effekt damit weiterhin wie gewohnt.
Auf kleineren Ansichten wird onFirstMove() dagegen nicht über eine Mausbewegung gestartet. Für diese Geräte erstellen wir im nächsten Schritt eine eigene Touch-Steuerung.
Damit verwenden Desktop und mobile Ansicht jeweils die Eingabemethode, die für das entsprechende Gerät beziehungsweise die entsprechende Darstellung vorgesehen ist.
TOUCH-BUTTON
Eine Steuerung für die mobile Ansicht hinzufügen
Da die Kreis-Maske auf dem Desktop durch den Mauszeiger gesteuert wird, benötigen wir für kleinere Displays eine alternative Bedienmöglichkeit.
Dafür erstellen wir einen runden Touch-Button, der am unteren Rand des Browserfensters eingeblendet wird. Später verwenden wir diesen Button, um die versteckte Ebene auf Touch-Geräten sichtbar zu machen.
Zunächst ergänzen wir nach dem Footer folgenden Button in unserer index.html:
Mit position: fixed bleibt der Button unabhängig von der aktuellen Scrollposition am unteren Rand des Browserfensters.
Der äußere Ring besitzt eine Breite und Höhe von 78px. Mit
left: calc(50% - 39px);
ziehen wir die Hälfte dieser Breite von der Mitte des Browserfensters ab und positionieren den Button dadurch horizontal mittig.
.btn_inner dient als relativer Bezugspunkt für die beiden Grafiken. Das Touch-Symbol wird innerhalb von .btn_touchabsolut über dem Ring positioniert und mit Flexbox horizontal und vertikal zentriert.
Der äußere Ring erhält unsere zuvor angelegte loop-Animation:
animation: loop 10s infinite forwards linear;
Dadurch dreht sich text-ring.svg kontinuierlich, während das Touch-Symbol in der Mitte stehen bleibt.
Auf Desktop-Ansichten benötigen wir den Button nicht. Deshalb blenden wir ihn ab unserem Desktop-Breakpoint von 1248px aus:
Anschließend reagieren wir auf touchstart. Dieses Ereignis wird ausgelöst, sobald der Benutzer den Button mit dem Finger berührt.
Mit:
const touch = e.touches[0];
holen wir uns den ersten aktiven Berührungspunkt. Anders als bei einem Mausereignis lesen wir die Koordinaten eines Touch-Events nicht direkt über e.pageX und e.pageY aus.
Die Position des Fingers erhalten wir stattdessen über:
touch.pageX
touch.pageY
Diese Werte übergeben wir an unsere CSS-Variablen --x und --y. Gleichzeitig machen wir die versteckte Ebene mit autoAlpha: 1 sichtbar.
Mit e.preventDefault() verhindern wir während touchstart die Standardaktion des Browsers für diese Berührung.
Sobald der Benutzer den Finger wieder vom Button nimmt, wird touchend ausgelöst.
Zu diesem Zeitpunkt befindet sich der beendete Berührungspunkt nicht mehr in e.touches. Deshalb verwenden wir:
const touch = e.changedTouches[0];
Damit erhalten wir die Koordinaten der Berührung, die gerade beendet wurde.
Anschließend blenden wir die versteckte Ebene mit autoAlpha: 0 wieder aus und setzen die Position der Maske auf die letzte Touch-Position.
Zum Abschluss animieren wir die Größe der Kreis-Maske zurück auf 0:
Wir verwenden Cookies, um Inhalte und Anzeigen zu personalisieren,
Funktionen für soziale Medien anbieten zu können und die Zugriffe auf
unsere Website zu analysieren.
Sie akzeptieren unsere Cookies, wenn Sie fortfahren diese Webseite zu
nutzen.
Datenschutzerklärung.