Front-End-Challenge angenommen: CSS 3D Cube

Veröffentlicht: 2022-03-10
Kurze Zusammenfassung ↬ Magst du Herausforderungen? Sind Sie bereit, eine Aufgabe zu übernehmen, die Sie noch nie zuvor gesehen haben, und dies unter einer Frist? Was ist, wenn Sie bei der Durchführung der Aufgabe auf ein scheinbar unlösbares Problem stoßen? Ich möchte meine Erfahrungen mit der erstmaligen Verwendung von CSS-3D-Effekten in einem realen Projekt teilen und Sie dazu inspirieren, Herausforderungen anzunehmen. Es war ein gewöhnlicher Tag, als Eugene, ein Manager bei CreativePeople , mir schrieb. Er schickte mir ein Video und erklärte, dass er ein Konzept für ein neues Projekt entwickle und sich frage, ob es für mich möglich sei, so etwas wie das im Video zu entwickeln.

Magst du Herausforderungen? Sind Sie bereit, eine Aufgabe zu übernehmen, die Sie noch nie zuvor gesehen haben, und dies unter einer Frist? Was ist, wenn Sie bei der Durchführung der Aufgabe auf ein scheinbar unlösbares Problem stoßen? Ich möchte meine Erfahrungen mit der erstmaligen Verwendung von CSS-3D-Effekten in einem realen Projekt teilen und Sie dazu inspirieren, Herausforderungen anzunehmen.

Es war ein ganz normaler Tag, als Eugene, ein Manager bei CreativePeople, mir schrieb. Er schickte mir ein Video und erklärte, dass er ein Konzept für ein neues Projekt entwickle und sich frage, ob es für mich möglich sei, so etwas wie das im Video zu entwickeln.

Weiterführende Literatur zu SmashingMag:

  • Beercamp: Ein Experiment mit CSS 3D
  • Responsive Formen mit Clip-Path erstellen und aus der Box ausbrechen
  • Lassen Sie uns mit hardwarebeschleunigtem CSS spielen

Es war ein 3D-Objekt (ein Quader, um genau zu sein), das sich um eine der Achsen drehte. Ich hatte bereits einige Erfahrung mit der Arbeit mit CSS 3D und eine Lösung begann sich in meinem Kopf zu formen. Ich googelte Schlüsselwörter wie „CSS 3D-Würfel“, um meine Ideen zu bestätigen, und antwortete Eugene, dass es möglich sei.

Mehr nach dem Sprung! Lesen Sie unten weiter ↓

Eugenes nächste Frage war, ob ich das Projekt übernehmen würde? Ich mag knifflige Aufgaben, also konnte ich nicht ablehnen. Damals war mir nicht klar, worauf ich mich einließ, aber ich war mehr als entschlossen.

Schärfen Sie Ihre Äxte

Erinnern wir uns an Achsen – keine Kriegsäxte, sondern die Zahlenstrahlen, dieselben Achsen wie im dreidimensionalen kartesischen Koordinatensystem, das wir in der Schule studiert haben. Wie uns Wikipedia sagt:

Das kartesische Koordinatensystem für einen dreidimensionalen Raum ist ein geordnetes Tripel von Linien (Achsen), die paarweise senkrecht sind, eine einzige Längeneinheit für alle drei Achsen haben und für jede Achse eine Ausrichtung haben.

Das folgende Bild zeigt, wie die Achsen in einem Webbrowser ausgerichtet sind.

Ein rechtshändiges dreidimensionales kartesisches Koordinatensystem, bei dem die Z-Achse zum Betrachter zeigt.
Ein rechtshändiges dreidimensionales kartesisches Koordinatensystem, bei dem die z-Achse zum Betrachter zeigt. (Bild: Wikimedia Commons) (Große Version anzeigen)

Die x-Achse verläuft horizontal, die y-Achse vertikal und die z-Achse scheint aus dem Bildschirm auf Sie zuzukommen. Der Nullwert der z-Achse ist die Ebene des Bildschirms. Merk dir das.

Die Perspektive klären

Um ein 3D-Objekt zu erstellen, brauchte ich ein Element (nennen wir es eine „Szene“) mit einer Perspektive. Die Perspektive ist die Tiefe der Szene und hängt von der Größe der darin enthaltenen Objekte ab.

 .scene { perspective: 800px; }

Wenn die Perspektive zu klein ist, könnten Objekte verzerrt werden. Wenn es zu groß ist, wird der 3D-Effekt auf nichts reduziert.

Sehen Sie sich den Stift jqgMvL von Anna Selezniova (@askd) auf CodePen an.

Außerdem gibt es nur einen Blickwinkel für alle Objekte in der Szene. Und der 3D-Effekt hängt von der Position des Blickwinkels ab.

Sehen Sie sich den Stift oxKzKv von Anna Selezniova (@askd) auf CodePen an.

Wie berechnen wir also die Perspektive? Ich habe festgestellt, dass es von der Rotationsachse abhängt. Für die x-Achse würde der Höhenwert multipliziert mit 4 passen. Für die y-Achse wäre es der Breitenwert multipliziert mit 4. Hier ist meine Zauberformel:

 const perspective = dimension * 4;

Von allen Seiten betrachtet

Nachdem ich die Perspektive festgelegt hatte, begann ich, ein 3D-Objekt zu erstellen. Ich habe mich für einen Würfel entschieden, weil er unkompliziert und vorhersehbar ist. Ein Cube-Element wird als reguläres div relativ positioniert mit definierter Breite und Höhe (z. B. 200px ) erstellt. Es verwandelt sich in ein 3D-Objekt durch die Eigenschaft transform-style mit dem Wert preserve-3d . Es weist den Browser an, alle verschachtelten Elemente gemäß den Regeln der 3D-Welt zu rendern.

In meinem Fall hat der Würfel sechs absolut positionierte Divs (oder „Seiten“). Die Klassennamen entsprechen den Anfangspositionen der Seiten ( back , left , right , top , bottom , front ). Hier ist das Markup:

 <div class="scene"> <div class="cube"> <div class="side back"></div> <div class="side left"></div> <div class="side right"></div> <div class="side top"></div> <div class="side bottom"></div> <div class="side front"></div> </div> </div>

Standardmäßig liegen alle Seiten auf einer Ebene. Also musste ich sie neu anordnen. So sieht das aus:

Sehen Sie sich den Pen mPNwPx von Anna Selezniova (@askd) auf CodePen an.

Und hier ist das resultierende CSS:

 .cube { position:relative; width: 200px; height: 200px; transform-style: preserve-3d; } .side { position: absolute; width: 200px; height: 200px; } .back { transform: translateZ(-100px); } .left { transform: translateX(-100px) rotateY(90deg); } .right { transform: translateX(100px) rotateY(90deg); } .top { transform: translateY(-100px) rotateX(90deg); } .bottom { transform: translateY(100px) rotateX(90deg); } .front { transform: translateZ(100px); }

Um den Würfel zu drehen, setze ich die transform des Würfelelements auf einen beliebigen Drehwinkel entlang der x-Achse:

 .cube { transform: rotateX(42deg); }

Überwindung der Mängel

Laut Aufgabe sollte ich den Würfel nur entlang der x-Achse drehen, also brauchte ich weder die linke noch die rechte Seite. Ich habe Beschriftungen hinzugefügt, um sie an den Anfangspositionen der verbleibenden Seiten auszurichten.

Ich fing an, den Würfel zu drehen und stellte fest, dass die Beschriftungen auf der Unter- und Rückseite verkehrt herum angezeigt wurden:

Sehen Sie sich den Stift GZVvMR von Anna Selezniova (@askd) auf CodePen an.

Um dieses Problem zu lösen, habe ich jede dieser Seiten entlang der x-Achse um 180 Grad gedreht:

 .back { transform: translateZ(-100px) rotateX(180deg); } .bottom { transform: translateY(100px) rotateX(270deg); }

Über den Bildschirm hinausgehen

Ich fing an, die Seiten mit echten Inhalten zu füllen und stieß sofort auf ein anderes Problem. Ich musste gepunktete 1-Pixel-Linien anzeigen, aber sie waren verschwommen und sahen schlecht aus.

Siehe Pen VjeBPg von Anna Selezniova (@askd) auf CodePen.

Ich erkannte bald, was das Problem war. Erinnern Sie sich an den 3D-TV-Werbespot, bei dem das Bild über den Bildschirm hinausragt? So ähnlich war das bei meinem Würfel.

Wenn Sie den Würfel von der linken oder rechten Seite betrachten könnten, würden Sie sehen, dass sein Mittelpunkt auf der Ebene des Bildschirms liegt (Null auf der z-Achse) und dass die Vorderseite außerhalb des Bildschirms liegt. Daher wurde es optisch vergrößert und verschwommen.

Sehen Sie sich den Pen WwVEMR von Anna Selezniova (@askd) auf CodePen an.

Um dieses Problem zu lösen, habe ich den Würfel entlang der z-Achse verschoben, um die Vorderseite an der Ebene des Bildschirms auszurichten:

 .cube { transform:translateZ(-100px); }

Hier ist der Würfel jetzt, fast fertig:

Sehen Sie sich den Pen Xdvery von Anna Selezniova (@askd) auf CodePen an.

Verwenden der magischen Zahlen

Ich denke, Sie haben bemerkt, dass ich die magische Zahl 100 verwende, um die Seiten entlang der Achse zu verschieben. Der Wert 100 ist genau die halbe Höhe meines Testwürfels. Warum halb so hoch? Denn das wäre der Radius eines Kreises, der in eine Seite des Würfels eingeschrieben ist (der anscheinend ein Quadrat ist).

 const offset = dimension / 2;

Wenn ich ein dreieckiges Prisma drehen müsste, würde der Kreis in ein Dreieck eingeschrieben werden. In diesem Fall lautet die Formel für den Offset wie folgt:

 const offset = dimension / (2 * Math.sqrt(3));

Wegblasen des Würfels

Um die Aufgabe als abgeschlossen zu betrachten, musste ich das Ergebnis in verschiedenen Browsern testen.

Das Bild, das ich im Internet Explorer sah, stürzte mich in eine Depression. Um eine Vorstellung davon zu bekommen, wovon ich spreche, sehen Sie sich die Demo unten in Ihrem bevorzugten Browser an. Ich habe eine Eigenschaft geändert, die dazu führte, dass der Cube im Internet Explorer falsch angezeigt wurde. Werfen Sie jedoch keinen Blick auf den Quellcode, bis Sie den Absatz unter der Demo unten gelesen haben.

Sehen Sie sich den Pen XKWMwV von Anna Selezniova (@askd) auf CodePen an.

Tatsache ist, dass Internet Explorer die transform-style Eigenschaft mit dem Wert preserve-3d nicht unterstützt. Ich habe davon erfahren, indem ich mir meine vertrauenswürdige Ressource Can I Use angeschaut habe (siehe Anmerkung 1). In der obigen Demo habe ich „ preserve-3d durch „ flat “ ersetzt. Wussten Sie das schon? Hey, ich habe dir gesagt, du sollst nicht gucken!

Ich war sauer, aber ich wollte nicht aufgeben. Ein Problem ist eine Gelegenheit, etwas Neues zu lernen. Außerdem hatte ich die Herausforderung angenommen.

Auf der Suche nach dem Drehpunkt

Ich habe nach einer Möglichkeit gesucht, ein 3D-Objekt zu erstellen, ohne transform-style: preserve-3d , und ich habe schließlich eine nützliche Eigenschaft entdeckt: transform-origin . Sie bestimmt den zentralen Punkt der Transformation eines Elements. Ich habe unten eine interaktive Demo erstellt, die Ihnen helfen wird, zu verstehen, wie es funktioniert:

Sehen Sie sich den Pen rLNmBp von Anna Selezniova (@askd) auf CodePen an.

Die 3D-Rotation des Elements in der Demo ist der Vorderseite eines Würfels sehr ähnlich, oder? Das habe ich benutzt.

(Haben Sie übrigens versucht, das Kontrollkästchen backface-visibility: hidden zu aktivieren? Diese Eigenschaft wird verwendet, um die Rückseite des Elements während der 3D-Transformation auszublenden.)

Nochmal von vorne anfangen

Ich fing an, den Würfel zu wiederholen. Ich musste nicht mit der Szene als Ganzes interagieren, also entfernte ich die perspective Eigenschaft des scene und fügte sie jeder 3D-Transformation hinzu, sodass sich jetzt jedes Element unabhängig transformiert. Außerdem lege ich neue Eigenschaften für jede Seite fest: transform-origin mit einem Wert, der der Position des Mittelpunkts des Würfels entspricht, und backface-visibility: hidden . So haben sich die Stile geändert:

 .scene { } .cube { position: relative; width: 200px; height: 200px; transform: perspective(800px) translateZ(-100px); } .side { position: absolute; transform-origin: 50% 50% -100px; backface-visibility: hidden; }

Ich musste die Seiten an die richtigen Stellen setzen. Aufgrund der transform-origin Eigenschaft musste ich sie nicht verschieben, sondern nur um die Achsen drehen. Es ist wie Magie! Mal sehen, wie es aussieht:

Siehe den Stift zBYwEm von Anna Selezniova (@askd) auf CodePen.

Hier ist das CSS für die Platzierung der Seiten:

 .back { transform: perspective(800px) rotateY(180deg); } .top { transform: perspective(800px) rotateX(90deg); } .bottom { transform: perspective(800px) rotateX(-90deg); } .front { transform: perspective(800px); }

Und hier sehen Sie den neuen Würfel in Aktion:

Sehen Sie sich den Stift wWvdXd von Anna Selezniova (@askd) auf CodePen an.

Cäsar zurückgeben, was Cäsar gehört

Der zweite Würfel sieht aus und dreht sich genauso wie der erste. Aber in diesem Fall müssen Sie jede Seite einzeln transformieren. Dies ist möglicherweise nicht ganz einfach, insbesondere wenn Sie den mittleren Drehwinkel steuern möchten.

Wenn Sie die Demo in Chrome öffnen, werden Sie außerdem sehen, dass die Seiten während der Drehung blinken – sehr frustrierend.

Am Ende habe ich beide Ansätze mit dem einfachen Test von transform-style: preserve-3d . Der erste Würfel ist der Standardwürfel. Der zweite Cube ist für Internet Explorer und Browser, die " preserve-3d nicht unterstützen.

Die Kraft der Mathematik nutzen

Schließlich musste ich einen Parallax-Effekt implementieren. Normalerweise reagiert dieser Effekt auf die Aktion des Benutzers, sei es die Position des Mauszeigers oder der Bildlaufleiste. Die Wirkung ist dabei drehwinkelabhängig.

Siehe den Stift QENyqm von Anna Selezniova (@askd) auf CodePen.

Also, welche Daten habe ich? Zuerst hatte ich die Start- und Endpunkte der Position der Beschriftung oder, um es einfach auszudrücken, ihren offset nach oben und unten von der Mitte einer Seite. Zweitens hatte ich den angle des Würfels.

Ich verbrachte Stunden damit, eine Formel zu entwickeln. Dann dämmerte es mir. Folgendes kam mir in den Sinn:

Graphen der Sinus- und Kosinusfunktionen
Diagramme der Sinus- und Kosinusfunktionen (Bild: Wikimedia Commons) (Große Version anzeigen)

Mit Hilfe von Sinus und Cosinus habe ich den Versatz jeder Beschriftung entsprechend dem Winkel leicht berechnet. Hier sind die Formeln, die ich mir ausgedacht habe:

 const front_offset = offset * sin(angle) * -1; const bottom_offset = offset * cos(angle); const back_offset = offset * sin(angle); const top_offset = offset * cos(angle) * -1;

Zusammenfassen

Die Aufgabe ist jetzt abgeschlossen, und ich kann mich über das Ergebnis freuen und es mit Ihnen teilen. Sehen Sie selbst, wie es funktioniert. Verwenden Sie die Scroll- oder Pfeiltasten, um den Promo-Block zu drehen. Versuchen Sie auch, das schwarze Dreieck rechts nach oben und unten zu ziehen, um den Drehwinkel manuell zu steuern (diese Funktion funktioniert leider nicht im Internet Explorer). Sieht ziemlich gut aus, oder? Und die Leistung ist ziemlich hoch (ca. 60 Bilder pro Sekunde).

Ich bin sehr froh, an der Entwicklung dieser Website mitgewirkt zu haben. Ich habe wertvolle Erfahrungen in der Arbeit mit CSS 3D gesammelt und viele interessante Eigenschaften entdeckt. Noch wichtiger ist, dass ich gelernt habe, dass man niemals aufgeben sollte; höchstwahrscheinlich finden Sie einen Weg, um die Aufgabe zu erfüllen.

Ich hoffe, Ihnen hat meine Geschichte gefallen und Sie sind nun bereit, sich neuen Herausforderungen zu stellen.