Ein grundlegender Überblick über die Erstellung eines responsiven, adaptiven und barrierefreien 3D-Spielmenüs.
In diesem Beitrag möchte ich Ihnen zeigen, wie Sie eine 3D-Spielmenükomponente erstellen können. Testen Sie die Demo ansehen.
<ph type="x-smartling-placeholder">Falls Sie Videos bevorzugen, finden Sie hier eine YouTube-Version dieses Beitrags:
Übersicht
Videospiele bieten Nutzern oft ein kreatives und ungewöhnliches Menü, und im 3D-Raum. Es ist beliebt, dass das Menü in neuen AR-/VR-Spielen und schwebt im Weltraum. Heute wiederholen wir die Grundlagen dieses Effekts, aber mit adaptivem Farbschema und Anpassungsmöglichkeiten für Nutzende die eingeschränkte Bewegung bevorzugen.
HTML
Ein Spielmenü besteht aus einer Liste von Schaltflächen. Um dies in HTML darzustellen, folgt:
<ul class="threeD-button-set">
<li><button>New Game</button></li>
<li><button>Continue</button></li>
<li><button>Online</button></li>
<li><button>Settings</button></li>
<li><button>Quit</button></li>
</ul>
Eine Liste von Schaltflächen kommt gut für Screenreader-Technologien und funktioniert auch ohne JavaScript oder CSS.
CSS
Der Stil der Schaltflächenliste ist in folgende übergeordnete Schritte unterteilt:
- Benutzerdefinierte Eigenschaften einrichten
- Ein Flexbox-Layout.
- Eine benutzerdefinierte Schaltfläche mit dekorativen Pseudoelementen.
- Elemente im 3D-Raum platzieren
Übersicht über benutzerdefinierte Eigenschaften
Mit benutzerdefinierten Eigenschaften lassen sich Werte unterscheiden, auf ansonsten zufällig aussehende Werte und vermeidet wiederholten Code und die Weitergabe von Daten an andere. Werte unter untergeordneten Elementen.
Unten finden Sie Medienabfragen, die als CSS-Variablen gespeichert sind. Diese werden auch als benutzerdefinierte Medien. Das sind globale und wird in verschiedenen Selektoren verwendet, um den Code prägnant und lesbar zu halten. Die Komponente des Spielemenüs verwendet Bewegungen Einstellungen, System-Farbe und Farbbereich Funktionen des Display.
@custom-media --motionOK (prefers-reduced-motion: no-preference);
@custom-media --dark (prefers-color-scheme: dark);
@custom-media --HDcolor (dynamic-range: high);
Mit den folgenden benutzerdefinierten Eigenschaften wird das Farbschema verwaltet und bei gedrückter Maustaste Positionswerte, mit denen das Spielmenü interaktiv gestaltet werden kann, wenn der Mauszeiger darauf bewegt wird Benennen: benutzerdefiniert Eigenschaften verbessern die Lesbarkeit des Codes, da der Anwendungsfall für den Wert oder einen Anzeigename für das Ergebnis des Werts.
.threeD-button-set {
--y:;
--x:;
--distance: 1px;
--theme: hsl(180 100% 50%);
--theme-bg: hsl(180 100% 50% / 25%);
--theme-bg-hover: hsl(180 100% 50% / 40%);
--theme-text: white;
--theme-shadow: hsl(180 100% 10% / 25%);
--_max-rotateY: 10deg;
--_max-rotateX: 15deg;
--_btn-bg: var(--theme-bg);
--_btn-bg-hover: var(--theme-bg-hover);
--_btn-text: var(--theme-text);
--_btn-text-shadow: var(--theme-shadow);
--_bounce-ease: cubic-bezier(.5, 1.75, .75, 1.25);
@media (--dark) {
--theme: hsl(255 53% 50%);
--theme-bg: hsl(255 53% 71% / 25%);
--theme-bg-hover: hsl(255 53% 50% / 40%);
--theme-shadow: hsl(255 53% 10% / 25%);
}
@media (--HDcolor) {
@supports (color: color(display-p3 0 0 0)) {
--theme: color(display-p3 .4 0 .9);
}
}
}
Kegelförmiger Hintergrund in hellem und dunklem Design
Das helle Design hat einen lebendigen Farbton von cyan
bis deeppink
Farbverlauf
und das dunkle Design hat einen subtilen, kegelförmigen Farbverlauf. Um mehr darüber zu erfahren,
ist mit konischen Farbverläufen möglich, siehe conic.style.
html {
background: conic-gradient(at -10% 50%, deeppink, cyan);
@media (--dark) {
background: conic-gradient(at -10% 50%, #212529, 50%, #495057, #212529);
}
}
3D-Perspektive aktivieren
Damit Elemente im 3D-Bereich einer Webseite vorhanden sind, kann ein Darstellungsbereich
Perspektive
muss initialisiert werden. Ich habe mich dafür entschieden, das Element body
aus der Perspektive zu sehen
und nutzte Darstellungsbereiche,
um den Stil zu erstellen, der mir gefiel.
body {
perspective: 40vw;
}
Dies ist die Art der Auswirkungsperspektive.
Stil der Schaltflächenliste für <ul>
gestalten
Dieses Element ist verantwortlich für das gesamte Layout der Schaltflächenliste, eine interaktive und schwebende 3D-Karte. Das können Sie auf folgende Weise erreichen:
Layout der Schaltflächengruppe
Flexbox kann das Containerlayout verwalten. Standardrichtung von Flex ändern
von Zeilen in Spalten mit flex-direction
und stellen Sie sicher, dass jedes Element die Größe
indem Sie für align-items
von stretch
in start
ändern.
.threeD-button-set {
/* remove <ul> margins */
margin: 0;
/* vertical rag-right layout */
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 2.5vh;
}
Richten Sie als Nächstes den Container als 3D-Space-Kontext ein und richten Sie die CSS-Datei clamp()
ein
um sicherzustellen, dass sich die Karte nicht über die lesbaren Drehungen hinaus dreht. Hinweis
dass der mittlere Wert für die Einschränkung eine benutzerdefinierte Eigenschaft ist, werden diese --x
und --y
Werte werden mit der Maus aus JavaScript festgelegt
Interaktion.
.threeD-button-set {
…
/* create 3D space context */
transform-style: preserve-3d;
/* clamped menu rotation to not be too extreme */
transform:
rotateY(
clamp(
calc(var(--_max-rotateY) * -1),
var(--y),
var(--_max-rotateY)
)
)
rotateX(
clamp(
calc(var(--_max-rotateX) * -1),
var(--x),
var(--_max-rotateX)
)
)
;
}
Wenn Bewegung für den Besucher kein Problem ist, fügen Sie dem Browser einen Hinweis hinzu,
die Transformation dieses Elements ständig mit
will-change
Aktivieren Sie außerdem die Interpolation, indem Sie für Transformationen einen transition
festlegen. Dieses
erfolgt, wenn die Maus mit der Karte interagiert. Dadurch wird eine
Rotationsänderungen. Die Animation läuft ständig
der den 3D-Raum darstellt, in dem sich die Karte befindet, selbst wenn eine Maus
nicht mit der Komponente interagiert.
@media (--motionOK) {
.threeD-button-set {
/* browser hint so it can be prepared and optimized */
will-change: transform;
/* transition transform style changes and run an infinite animation */
transition: transform .1s ease;
animation: rotate-y 5s ease-in-out infinite;
}
}
Bei der rotate-y
-Animation wird nur der mittlere Keyframe auf 50%
festgelegt, da das
verwendet der Browser standardmäßig den Standardstil des Elements für 0%
und 100%
. Dieses
steht für abwechselnde Animationen, deren Anfang und Ende identisch sein müssen
. Es ist eine großartige Möglichkeit, unendliche abwechselnde Animationen zu artikulieren.
@keyframes rotate-y {
50% {
transform: rotateY(15deg) rotateX(-6deg);
}
}
Stil für <li>
-Elemente festlegen
Jedes Listenelement (<li>
) enthält die Schaltfläche und die dazugehörigen Rahmenelemente. Die
Der Stil von display
wurde geändert, sodass für das Element kein
::marker
Der position
-Stil
ist auf relative
gesetzt, sodass die Pseudoelemente der nächsten Schaltfläche
innerhalb des gesamten Bereichs, den die Schaltfläche verbraucht.
.threeD-button-set > li {
/* change display type from list-item */
display: inline-flex;
/* create context for button pseudos */
position: relative;
/* create 3D space context */
transform-style: preserve-3d;
}
Stil für <button>
-Elemente festlegen
Die Gestaltung von Schaltflächen kann schwierig sein. Es gibt viele Status und Interaktionstypen die Sie berücksichtigen müssen. Diese Schaltflächen werden durch die Ausgewogenheit schnell komplex. Pseudo-Elemente, Animationen und Interaktionen.
Anfängliche <button>
-Stile
Unten sind die grundlegenden Stile aufgeführt, die die anderen Stadien unterstützen.
.threeD-button-set button {
/* strip out default button styles */
appearance: none;
outline: none;
border: none;
/* bring in brand styles via props */
background-color: var(--_btn-bg);
color: var(--_btn-text);
text-shadow: 0 1px 1px var(--_btn-text-shadow);
/* large text rounded corner and padded*/
font-size: 5vmin;
font-family: Audiowide;
padding-block: .75ch;
padding-inline: 2ch;
border-radius: 5px 20px;
}
Pseudoelemente der Schaltfläche
Die Ränder der Schaltfläche sind keine traditionellen Rahmen, sie befinden sich an einer absoluten Position. Pseudo-Elemente mit Rahmen enthalten.
Diese Elemente sind entscheidend für die Darstellung der bisher bekannten 3D-Perspektive. festgelegt ist. Eines dieser Pseudoelemente wird von der Schaltfläche weggeschoben, und eines wird näher am Nutzer gezogen. Am deutlichsten wirkt sich der Effekt in der Tasten oben und unten.
.threeD-button button {
…
&::after,
&::before {
/* create empty element */
content: '';
opacity: .8;
/* cover the parent (button) */
position: absolute;
inset: 0;
/* style the element for border accents */
border: 1px solid var(--theme);
border-radius: 5px 20px;
}
/* exceptions for one of the pseudo elements */
/* this will be pushed back (3x) and have a thicker border */
&::before {
border-width: 3px;
/* in dark mode, it glows! */
@media (--dark) {
box-shadow:
0 0 25px var(--theme),
inset 0 0 25px var(--theme);
}
}
}
3D-Transformationsstile
Unter „transform-style
“ ist preserve-3d
festgelegt, damit die Kinder Platz haben
sich selbst auf der z
-Achse. transform
ist auf --distance
festgelegt
benutzerdefinierte Eigenschaft, die durch Hover- und
fokus.
.threeD-button-set button {
…
transform: translateZ(var(--distance));
transform-style: preserve-3d;
&::after {
/* pull forward in Z space with a 3x multiplier */
transform: translateZ(calc(var(--distance) / 3));
}
&::before {
/* push back in Z space with a 3x multiplier */
transform: translateZ(calc(var(--distance) / 3 * -1));
}
}
Bedingte Animationsstile
Wenn die Nutzenden mit Bewegung einverstanden sind, weist die Schaltfläche dem Browser darauf hin,
Transformationseigenschaft sollte geändert werden können und ein Übergang für
transform
- und background-color
-Properties. Beachten Sie den Unterschied in
hatte ich das Gefühl, dass es
eine schöne gestaffelte Wirkung erzeugt.
.threeD-button-set button {
…
@media (--motionOK) {
will-change: transform;
transition:
transform .2s ease,
background-color .5s ease
;
&::before,
&::after {
transition: transform .1s ease-out;
}
&::after { transition-duration: .5s }
&::before { transition-duration: .3s }
}
}
Interaktionsstile für Mauszeiger und Fokus
Das Ziel der Interaktionsanimation besteht darin, die Schichten der
Schaltfläche mit flachem Design. Legen Sie dazu die Variable --distance
fest,
anfänglich auf 1px
. Mit dem Selektor im folgenden Codebeispiel wird geprüft,
Sie können sehen, ob ein Gerät den Mauszeiger auf die Schaltfläche bewegt oder darauf fokussiert wird, wenn ein Gerät
Fokusanzeige und nicht aktiviert ist. In diesem Fall übernimmt das CSS
Folgendes:
- Wenden Sie die Hintergrundfarbe an, über die der Mauszeiger darauf bewegt wird.
- Strecke vergrößern
- Füge einen Entspannungseffekt hinzu.
- Verteilen Sie die Übergänge des Pseudoelements.
.threeD-button-set button {
…
&:is(:hover, :focus-visible):not(:active) {
/* subtle distance plus bg color change on hover/focus */
--distance: 15px;
background-color: var(--_btn-bg-hover);
/* if motion is OK, setup transitions and increase distance */
@media (--motionOK) {
--distance: 3vmax;
transition-timing-function: var(--_bounce-ease);
transition-duration: .4s;
&::after { transition-duration: .5s }
&::before { transition-duration: .3s }
}
}
}
Die 3D-Perspektive war für die Bewegungseinstellung reduced
immer noch ansprechend.
Die Elemente oben und unten stellen den Effekt auf subtile Weise zur Verfügung.
Kleine Verbesserungen mit JavaScript
Die Benutzeroberfläche kann über Tastaturen, Screenreader, Gamepads, Touchscreens mit der Maus. Wir können aber JavaScript-Elemente hinzufügen, von Szenarien.
Unterstützende Pfeiltasten
Mit der Tabulatortaste navigiere ich gut im Menü.
oder Joysticks, um den Fokus auf einem Gamepad zu verschieben. Die
roving-ux-Bibliothek, die häufig für GUI verwendet wird
Challenge-Oberflächen übernehmen die Pfeiltasten für uns. Der Code unten teilt dem
Bibliothek, um den Fokus innerhalb von .threeD-button-set
abzufangen und ihn auf das
Untergeordnete Elemente.
import {rovingIndex} from 'roving-ux'
rovingIndex({
element: document.querySelector('.threeD-button-set'),
target: 'button',
})
Interaktion mit Maus-Parallaxe
Die Bewegung der Maus und das Neigen des Menüs soll AR und VR imitieren. Videospiel-Oberflächen, bei denen Sie statt der Maus einen virtuellen Zeiger verwenden können. Es kann lustig sein, wenn die Elemente den Zeiger sehr bewusst sind.
Da dies eine kleine Zusatzfunktion ist, platzieren wir die Interaktion hinter einer Abfrage von
die Bewegungspräferenz der Nutzenden. Speichern Sie bei der Einrichtung auch die Liste der Schaltflächen.
Komponente mit querySelector
in den Speicher ein und speichern die Begrenzungen des Elements
menuRect
. Legen Sie anhand dieser Grenzen den Rotationsversatz fest, der auf die Karte angewendet wird.
basierend auf der Mausposition.
const menu = document.querySelector('.threeD-button-set')
const menuRect = menu.getBoundingClientRect()
const { matches:motionOK } = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Als Nächstes benötigen wir eine Funktion, die die x
- und y
-Mauspositionen akzeptiert und
einen Wert, mit dem die Karte rotiert wird. Die folgende Funktion verwendet die Maus,
um zu ermitteln, in welcher Seite der Box sie sich befindet. Die
delta wird von der Funktion zurückgegeben.
const getAngles = (clientX, clientY) => {
const { x, y, width, height } = menuRect
const dx = clientX - (x + 0.5 * width)
const dy = clientY - (y + 0.5 * height)
return {dx,dy}
}
Beobachten Sie abschließend die Mausbewegung und übergeben Sie die Position an die Funktion getAngles()
.
und verwenden Sie die Deltawerte als benutzerdefinierte Eigenschaftsstile. Durch 20 geteilt, um die
und es weniger verdreht, gibt es vielleicht eine bessere Methode. Wenn Sie
Wir haben die Requisiten --x
und --y
in die Mitte einer
clamp()
-Funktion verhindert, dass die Mausposition zu stark gedreht wird.
an einer unleserlichen Position.
if (motionOK) {
window.addEventListener('mousemove', ({target, clientX, clientY}) => {
const {dx,dy} = getAngles(clientX, clientY)
menu.attributeStyleMap.set('--x', `${dy / 20}deg`)
menu.attributeStyleMap.set('--y', `${dx / 20}deg`)
})
}
Übersetzungen und Wegbeschreibungen
Beim Testen des Spielmenüs in anderen Schreibmodi Sprachen.
<button>
-Elemente haben den Stil !important
für writing-mode
im Nutzer
Agent-Stylesheet. Das bedeutete, dass der HTML-Code des Spielmenüs geändert werden musste,
das gewünschte Design. Das Ändern der Schaltflächenliste in eine Liste von Links aktiviert logische
Eigenschaften des Menüs, da <a>
-Elemente keinen Browser haben
bereitgestellten Stil !important
.
Fazit
Jetzt, wo Sie wissen, wie ich das gemacht habe, wie würdest du... ‽ 🙂 Kannst du einen Beschleunigungsmesser hinzufügen? Interaktion mit dem Menü, sodass sich das Menü drehen soll, wenn Sie Ihr Telefon als Kachel verwenden? Können wir uns verbessern? keine Bewegungserkennung?
Lassen Sie uns unsere Herangehensweisen diversifizieren und alle Möglichkeiten kennenlernen, wie wir das Web entwickeln können. Erstelle eine Demo, twittere mir Links und ich füge sie hinzu im Abschnitt „Community-Remixe“ weiter unten.
Community-Remixe
Hier gibt es noch nichts zu sehen.