Erstellen einer 3D-Würfel-Bildergalerie

Avatar of Kushagra Gour
Kushagra Gour am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Der folgende Text ist ein Gastbeitrag von Kushagra Gour (@chinchang457). Kushagra schrieb mir, um mir eine unterhaltsame interaktive Demo zu zeigen, die er erstellt hat. Sie berührt viele Konzepte von 3D-Transformationen in CSS, einem Thema, das wir hier noch nicht viel behandelt haben. Hier übernimmt Kushagra das Wort, um diese Konzepte anhand einer Demo zu erklären.

Ich habe kürzlich meine Website neu gestaltet und mir für die Homepage und den Header eine 2-seitige 3D-Würfel-Idee ausgedacht. Beim Darüberfahren dreht sie sich zwischen meinem Profilbild und dem Twitter-Link. Dabei dachte ich, warum nicht die Idee zu einem vollständigen 6-seitigen Würfel erweitern, der als Bildergalerie verwendet werden könnte. Hier ist, was mir eingefallen ist!

Sehen Sie den Pen 3D-Würfel-Bildergalerie von Kushagra Gour (@chinchang) auf CodePen

Diese Anleitung beschreibt, wie Sie so etwas erstellen können, wobei die CSS3 3D-Konzepte hervorgehoben werden.

Den Würfel aufbrechen

Es ist durch den Blick auf den Würfel offensichtlich, dass die 6 Seiten des Würfels 6 verschiedene HTML-Elemente sein werden. In diesem Fall sechs <div>-Elemente. Da sie als ein Würfel rotiert werden müssen, müssen sie sich in einem Container-Element befinden. Wenn wir diese Grundstruktur codieren, hätten wir etwas wie dies

<div class="cube">
    <div class="cube-face"></div>
    <div class="cube-face"></div>
    <div class="cube-face"></div>
    <div class="cube-face"></div>
    <div class="cube-face"></div>
    <div class="cube-face"></div>
 </div>

Da wir jede Seite zum Stylen referenzieren müssen, sollten wir ihnen entsprechende Klassen geben.

<div class="cube">
    <div class="cube-face  cube-face-front"></div>
    <div class="cube-face  cube-face-back"></div>
    <div class="cube-face  cube-face-left"></div>
    <div class="cube-face  cube-face-right"></div>
    <div class="cube-face  cube-face-top"></div>
    <div class="cube-face  cube-face-bottom"></div>
 </div>

Styling der Seiten

Wir sehen noch nichts. Geben wir den Seiten also etwas Dimension und Stil.

$size: 150px; // cube length
.cube {
  width: $size;
  height: $size;
  position: relative;
}
.cube-face {
  width: inherit;
  height: inherit;
  position: absolute;
  background: red;
  opacity: 0.5;
}

Sehen Sie den Pen 3d cube gallery tutorial – P1 von Kushagra Gour (@chinchang) auf CodePen

Beachten Sie, dass jede Würfelseite position: absolute hat, damit sie übereinander an einer Stelle gestapelt werden. Jetzt können wir jede Seite auswählen und entsprechend positionieren.

Außerdem habe ich jeder Seite eine Opazität gegeben, damit wir durch sie hindurchsehen und sehen können, was passiert.

CSS3 3D-Konzepte

Lernen wir einige Konzepte von CSS3 3D kennen. Um die Vorderseite ein wenig näher an die Augen zu bringen, verschieben wir sie auf der Z-Achse.

.cube-face-front {
  color: blue;
  transform: translate3d(0, 0, 20px);
}

Sie werden noch keinen Unterschied sehen. Lassen Sie uns verstehen, warum.

Perspektive

Wie auf MDN erwähnt

Die CSS-Eigenschaft `perspective` bestimmt den Abstand zwischen der z=0-Ebene und dem Benutzer, um dem 3D-positionierten Element eine Perspektive zu verleihen.

Einfach ausgedrückt bestimmt ihr Wert das Ausmaß der 3D-Wirkung im Raum. Je geringer der Wert dieser Eigenschaft, desto ausgeprägter ist der 3D-Effekt. Ohne diese Eigenschaft werden die Elemente mit einer Parallelprojektion auf dem Bildschirm gerendert, bei der die Projektionslinien parallel zueinander verlaufen. Daher wird ein Element, egal wie nah es sich Ihnen nähert oder von Ihnen entfernt, immer die gleiche Größe behalten, im Gegensatz zur realen Welt. (Mehr Informationen zu `perspective`).

Wir setzen diese Eigenschaft auf den Elternelement unseres Würfels, damit alle seine Kinder (Seiten) von einer gemeinsamen Perspektive betroffen sind, so:

.cube {
  width: $size;
  height: $size;
  position: relative;
  
  perspective: 600px;
}

Wie erwartet erscheint die Vorderseite jetzt größer. Aber etwas fehlt immer noch.

`transform-style`

Selbst nachdem wir unserer Szene Perspektive verliehen haben, haben wir immer noch ein Problem. Die Vorderseite sollte idealerweise über allen anderen Seiten erscheinen und sie dahinter verstecken. Aber das tut sie nicht.

Der Grund ist, dass unserem Würfelcontainer kein 3D-Rendering-Kontext fehlt, der wie folgt auf CSSWG definiert ist:

Eine Hierarchie von Containing Blocks mit einem oder mehreren Ebenen, die durch Elemente mit einem berechneten Wert für die Eigenschaft `transform-style` von `preserve-3d` instanziiert werden und deren Elemente ein gemeinsames dreidimensionales Koordinatensystem teilen.

Ohne ein Element, das die `transform-style`-Eigenschaft auf `preserve-3d` gesetzt hat, werden seine Kinder abgeflacht gerendert und haben keinen Stapelkontext. Selbst wenn wir die Vorderseite auf der Z-Achse näher gebracht haben, wurde sie weiterhin an ihrem ursprünglichen z-index gerendert, ohne Berücksichtigung ihrer Position im 3D-Raum.

Versuchen Sie, dem `.cube`-Element diese Eigenschaft zu geben und sehen Sie, was passiert.

.cube {
  width: $size;
  height: $size;
  position: relative;
  
  perspective: 600px;
  transform-style: preserve-3d;
}

Es hat funktioniert. Jetzt, da wir unser 3D-System eingerichtet haben, verwandeln wir es in einen Würfel!

Positionieren der Seiten

Wir nehmen eine Seite nach der anderen und positionieren sie an ihrem geeigneten Platz. Zuerst verstehen wir das Koordinatensystem in CSS. Wenn wir eine unserer Würfelseiten nehmen, sieht es so aus:

Vorderseite flach liegend, die Z-Achse kommt auf uns zu

Wie Sie sehen, kommt die Z-Achse direkt aus dem Element aus dem Bildschirm heraus. Wenn wir also die Vorderseite positiv auf der Z-Achse verschieben, erscheint sie uns näher. Ein wichtiger Hinweis hier ist, dass dieses Koordinatensystem lokal für dieses Element ist. Schauen wir uns das genauer an.

Wir verwenden erneut unsere Vorderseite und drehen sie ein wenig um ihre Y-Achse.

.cube-face-front {
  transform: rotateY(40deg);
}

So sieht unsere Vorderseite nach der Drehung aus

Achsen drehen sich mit der Seite.

Beachten Sie, wie sich die Achsen zusammen mit dem Element gedreht haben. Das bedeutet, dass die Z-Achse nicht mehr direkt auf uns zukommt. Stattdessen ist sie in Richtung des Elements ausgerichtet. Wenn wir sie also jetzt entlang der Z-Achse bewegen würden, würde sie sich in die Richtung bewegen, in die das Element zeigt.

Dies ist das Konzept, das wir verwenden werden, um jede Seite unseres Würfels zu positionieren. Nehmen wir an, die Mitte des Würfels liegt in der 2D-Ebene des Bildschirms. Die Würfelseiten müssen dann im 3D-Raum um sie herum positioniert werden. Denken Sie daran: **Wir drehen die Seite, damit sie in die erforderliche Richtung zeigt, und verschieben sie dann auf der Z-Achse**.

Vorderseite

Hier gibt es nichts zu drehen. Verschieben Sie einfach die Vorderseite um die halbe Länge des Würfels nach vorne.

.cube-face-front {
  transform: translate3d(0, 0, $size/2);
}

Rückseite

Die Rückseite zeigt in die entgegengesetzte Richtung zur Vorderseite. Das bedeutet, sie muss um 180 Grad um die Y-Achse gedreht werden, bevor sie wie folgt verschoben wird.

.cube-face-back {
  transform: rotateY(180deg) translate3d(0, 0, $size/2);
}

2 Seiten erledigt. Noch 4 zu gehen.

Linke Seite

Falls Sie noch Zweifel haben, wie die Transformationen durchgeführt werden, lassen Sie uns diese Seite anhand einiger visueller Darstellungen verstehen.

So sieht die linke Seite im Moment aus, flach liegend in der 2D-Ebene (z=0)

Linke Seite: in der 2D-Ebene

Da die linke Seite nach links zeigen muss, geben wir ihr eine Drehung von 90 Grad.

Linke Seite: nach der Drehung

Und wie bei jeder Seite verschieben wir sie auf ihrer Z-Achse.

Linke Seite: nach der Verschiebung

Dies ist das endgültige CSS für die linke Seite.

.cube-face-left {
  transform: rotateY(-90deg) translate3d(0, 0, $size/2);
}

Rechte Seite

Dies ist ähnlich wie die linke Seite, außer einer positiven Drehung.

.cube-face-right {
  transform: rotateY(90deg) translate3d(0, 0, $size/2);
}

Oberseite

Diese Seite muss um 90 Grad um die X-Achse gedreht werden, damit sie nach oben zeigt.

.cube-face-top {
  transform: rotateX(90deg) translate3d(0, 0, $size/2);
}

Unterseite

Ähnlich positionieren wir die Unterseite durch eine negative Drehung.

.cube-face-bottom {
  transform: rotateX(-90deg) translate3d(0, 0, $size/2);
}

Dies schließt die Positionierung der Seiten ab und wir haben nun unseren fertigen Würfel mit dem folgenden endgültigen CSS (ich habe jeder Seite auch zufällige Farben hinzugefügt, um sie zu unterscheiden).

$size: 150px; // cube length
.cube {
  margin: 100px;
  width: $size;
  height: $size;
  position: relative;
  
  perspective: 600px;
  transform-style: preserve-3d;
}
.cube-face {
  width: inherit;
  height: inherit;
  position: absolute;
  background: red;
  opacity: 0.8;
}
.cube-face-front {
  background: yellow;
  transform: translate3d(0, 0, $size/2);
} 
.cube-face-back {
  background: orange;
  transform: rotateY(180deg) translate3d(0, 0, $size/2);
} 
.cube-face-left {
  background: green;
  transform: rotateY(-90deg) translate3d(0, 0, $size/2);
} 
.cube-face-right {
  background: magenta;
  transform: rotateY(90deg) translate3d(0, 0, $size/2);
} 
.cube-face-top {
  background: blue;
  transform: rotateX(90deg) translate3d(0, 0, $size/2);
} 
.cube-face-bottom {
  background: red;
  transform: rotateX(-90deg) translate3d(0, 0, $size/2);
}

Um den Würfel zu drehen, können wir einfach Rotationen auf das `.cube`-Element anwenden. Versuchen Sie, ihm eine Drehung von 180 Grad um die Y-Achse (vertikal) zu geben.

.cube {
  margin: 100px;
  width: $size;
  height: $size;
  position: relative;
  
  perspective: 600px;
  transform-style: preserve-3d;
  transform: rotateY(180deg);
}

Sie sollten etwas wie dies sehen

Sehen Sie den Pen 3d cube gallery tutorial – P2 von Kushagra Gour (@chinchang) auf CodePen

Fällt Ihnen etwas auf? Wir haben den Würfel um 180 Grad um seine vertikale Achse gedreht. Wir hätten jetzt die Rückseite anstelle der Vorderseite sehen sollen. Wir sehen sie, aber sie erscheint aus irgendeinem Grund kleiner. Was haben wir falsch gemacht?

Perspektive korrigieren

Wenn Sie sich erinnern, haben wir die `perspective`-Eigenschaft auf den Würfelcontainer (`.cube`) angewendet. Und als wir dieses Element gerade gedreht haben, hat sich der durch den Fluchtpunkt markierte Fluchtpunkt zusammen mit ihm gedreht. Der Fluchtpunkt, der sich ursprünglich irgendwo hinter der 2D-Ebene befand, kam nach der Drehung vor die 2D-Ebene und verursachte das Problem.

Was wir idealerweise wollen, ist, dass sich die Perspektive nie ändert und konstant bleibt, egal welches Element wir transformieren.

Wie beheben wir das? Wir umschließen alle unsere Elemente mit einem weiteren DIV, dem wir die perspective-Eigenschaft geben.

<div class="scene">
  <div class="cube">
    <div class="cube-face  cube-face-front"></div>
    <div class="cube-face  cube-face-back"></div>
    <div class="cube-face  cube-face-left"></div>
    <div class="cube-face  cube-face-right"></div>
    <div class="cube-face  cube-face-top"></div>
    <div class="cube-face  cube-face-bottom"></div>
  </div>
</div>
.scene {
  margin: 100px;
  width: $size;
  height: $size;
  
  perspective: 600px;
}
.cube {
  position: relative;
  width: inherit;
  height: inherit;
  
  transform-style: preserve-3d;
  transform: rotateY(180deg);
}

Überprüfen Sie das Ergebnis jetzt und alles sollte wie erwartet aussehen.

Versuchen Sie, ihm verschiedene Rotationen wie transform: rotateX(30deg) rotateY(30deg) zu geben, um damit ein wenig zu spielen. Wenn Sie fertig sind, entfernen Sie die transform-Eigenschaft.

Interaktivität hinzufügen

Nun fügen wir einige Steuerelemente hinzu, um durch die Galerie zu navigieren. Dafür verwenden wir einen netten Trick namens **Checkbox Hack**. Obwohl wir Radio-Buttons verwenden (da immer nur einer ausgewählt sein wird) anstelle von Checkboxen, bleibt das Konzept dasselbe. Sie können mehr über den Checkbox Hack in Chris Coyiers Artikel lesen.

Wir gehen nicht zu sehr ins Detail und fügen die Radio-Buttons zu unserem HTML hinzu.

<!-- CONTROLS -->      
<input type="radio" checked id="radio-front" name="select-face"/>    
<input type="radio" id="radio-back" name="select-face"/>
<input type="radio" id="radio-left" name="select-face"/>
<input type="radio" id="radio-right" name="select-face"/>
<input type="radio" id="radio-top" name="select-face"/>
<input type="radio" id="radio-bottom" name="select-face"/>
<div class="scene">
  <div class="cube">
    <div class="cube-face  cube-face-front"></div>
    <div class="cube-face  cube-face-back"></div>
    <div class="cube-face  cube-face-left"></div>
    <div class="cube-face  cube-face-right"></div>
    <div class="cube-face  cube-face-top"></div>
    <div class="cube-face  cube-face-bottom"></div>
  </div>
</div>

und folgendes CSS, um die Rotation des Würfels mit den Radio-Buttons zu verbinden.

#radio-back:checked ~ .scene .cube {
  transform: rotateY(180deg);
} 
#radio-left:checked ~ .scene .cube {
  transform: rotateY(90deg);
} 
#radio-right:checked ~ .scene .cube {
  transform: rotateY(-90deg);
}
#radio-top:checked ~ .scene .cube {
  transform: rotateX(-90deg);
}  
#radio-bottom:checked ~ .scene .cube {
  transform: rotateX(90deg);
}

Im obigen CSS geben wir einfach an, wann jeder Radio-Button angeklickt wird, welche Rotation der Würfel zu diesem Zeitpunkt haben soll.

Endgültiger Code

Um es gefälliger zu gestalten, fügen wir dem Würfel einen Übergangseffekt und eine ordnungsgemäße Ausrichtung hinzu, um den folgenden Code zu erhalten.

<!-- CONTROLS -->
<input type="radio" checked id="radio-front" name="select-face"/>    
<input type="radio" id="radio-left" name="select-face"/>
<input type="radio" id="radio-right" name="select-face"/>
<input type="radio" id="radio-top" name="select-face"/>
<input type="radio" id="radio-bottom" name="select-face"/>
<input type="radio" id="radio-back" name="select-face"/>

<div></div><!-- separator -->

<div class="scene">
  <div class="cube">
      <div class="cube-face  cube-face-front"></div>
      <div class="cube-face  cube-face-back"></div>
      <div class="cube-face  cube-face-left"></div>
      <div class="cube-face  cube-face-right"></div>
      <div class="cube-face  cube-face-top"></div>
      <div class="cube-face  cube-face-bottom"></div>
   </div>
</div>
$size: 150px; // cube length
body {
  text-align: center;
  padding: 50px;
} 
.scene {
  display: inline-block;
  margin-top: 50px;
  width: $size;
  height: $size;
  
  perspective: 600px;
}
.cube {
  position: relative;
  width: inherit;
  height: inherit;
  
  transform-style: preserve-3d;
  transition: transform 0.6s;
}
.cube-face {
  width: inherit;
  height: inherit;
  position: absolute;
  background: red;
  opacity: 0.8;
}
// faces
.cube-face-front {
  background: yellow;
  transform: translate3d(0, 0, $size/2);
}  
.cube-face-back {
  background: black;
  transform: rotateY(180deg) translate3d(0, 0, $size/2);
} 
.cube-face-left {
  background: green;
  transform: rotateY(-90deg) translate3d(0, 0, $size/2);
} 
.cube-face-right {
  background: magenta;
  transform: rotateY(90deg) translate3d(0, 0, $size/2);
} 
.cube-face-top {
  background: blue;
  transform: rotateX(90deg) translate3d(0, 0, $size/2);
} 
.cube-face-bottom {
  background: red;
  transform: rotateX(-90deg) translate3d(0, 0, $size/2);
}  
// controls 
#radio-back:checked ~ .scene .cube {
  transform: rotateY(180deg); 
} 
#radio-left:checked ~ .scene .cube {
  transform: rotateY(90deg); 
} 
#radio-right:checked ~ .scene .cube {
  transform: rotateY(-90deg); 
}
#radio-top:checked ~ .scene .cube {
  transform: rotateX(-90deg); 
}  
#radio-bottom:checked ~ .scene .cube {
  transform: rotateX(90deg); 
}

Durch Hinzufügen von background-image zu allen Seiten erhalten wir das Endergebnis.

Sehen Sie den Pen 3D-Würfel-Bildergalerie von Kushagra Gour (@chinchang) auf CodePen

Ich hoffe, Sie haben diese 3D-Fahrt genossen und werden damit wirklich erstaunliche Dinge erstellen!