Duyarlı, uyarlanabilir ve erişilebilir bir 3D oyun menüsünün nasıl oluşturulacağına ilişkin temel bir genel bakış.
Bu gönderide, 3D oyun menüsü bileşeni oluşturma konusunda düşüncelerimi paylaşmak istiyorum. Şunu deneyin: demo.
Video kullanmayı tercih ederseniz bu gönderinin YouTube versiyonunu kullanabilirsiniz:
Genel Bakış
Video oyunlarında kullanıcılara çoğu zaman animasyonlu sırları içeren yaratıcı ve alışılmadık bir menü çok daha iyi hale gelir. Yeni AR/sanal gerçeklik oyunlarında popüler olduğu için menü 250 metrelik bir oyun. Bugün bu efektin temellerini yeniden oluşturacağız, ancak Ayrıca, uyarlanabilir renk şeması ve kullanıcılar için konaklama olanağı daha az hareket etmeyi tercih eder.
HTML
Oyun menüsü, düğmelerden oluşan bir listedir. Bunu HTML'de göstermenin en iyi yolu şöyle olur:
<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>
Düğmelerden oluşan bir liste kendisini ekran okuyucu teknolojilerine ve JavaScript veya CSS olmadan çalışır.
CSS
Düğme listesinin stilini belirlemek aşağıdaki üst düzey adımlara ayrılır:
- Özel özellikleri ayarlama.
- Flexbox düzeni.
- Dekoratif sözde öğeler içeren özel bir düğme.
- Öğeleri 3D alana yerleştirme.
Özel özelliklere genel bakış
Özel özellikler, kullanıcılara anlamlı bulgular sunarak aksi takdirde rastgele görünen değerlere sahip olur, yinelenen kodlardan ve paylaşımdan kaçınılır. değerleri anlamaya başladım.
Aşağıda, özel olarak da bilinen CSS değişkenleri olarak kaydedilen medya sorguları verilmiştir. medya. Bunlar küresel ve çeşitli seçicilerde kodun kısa ve okunaklı olması için kullanılacak. İlgili içeriği oluşturmak için kullanılan oyun menüsü bileşeni hareket ediyor tercihler, sistem rengi şema, ve renk aralığı özelliklerini görüntüleyin.
@custom-media --motionOK (prefers-reduced-motion: no-preference);
@custom-media --dark (prefers-color-scheme: dark);
@custom-media --HDcolor (dynamic-range: high);
Aşağıdaki özel özellikler renk şemasını yönetir ve fareyi basılı tutun oyun menüsünü etkileşimli hale getirmek için konum değerleri. Özel adlandırma özellikleri kullanmak, değerin veya bir varlığın kullanım alanını ortaya koyduğundan değerin sonucunun kolay adı.
.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);
}
}
}
Açık ve koyu temalı arka plan konik arka planlar
Açık temada, canlı cyan
- deeppink
konikliği vardır
gradyan
koyu temada ise koyu, ince bir konik gradyan vardır. YouTube'da
konik renklendirmelerle yapılabilir; bkz. conic.style.
html {
background: conic-gradient(at -10% 50%, deeppink, cyan);
@media (--dark) {
background: conic-gradient(at -10% 50%, #212529, 50%, #495057, #212529);
}
}
3D perspektifi etkinleştirme
Öğelerin bir web sayfasının 3D alanında bulunması için,
perspektif
başlatılması gerekir. Perspektifi body
öğesine koymayı seçtim
ve hoşuma giden stili oluşturmak için görüntü alanı birimlerini kullandım.
body {
perspective: 40vw;
}
Bu, bakış açısının sunabileceği etki türünü ifade eder.
<ul>
düğme listesinin stilini belirleme
Bu öğe, genel düğme listesi makro düzeninin yanı sıra etkileşimli ve 3D kayan kart olma. Bunu aşağıdaki şekilde yapabilirsiniz.
Düğme grubu düzeni
Flexbox, kapsayıcı düzenini yönetebilir. Esnek sıcaklığın varsayılan yönünü değiştirme
flex-direction
içeren satırlardan sütunlara uygulayın ve her bir öğenin
align-items
için stretch
yerine start
olarak değiştirilerek içeriğini inceleyebilirsiniz.
.threeD-button-set {
/* remove <ul> margins */
margin: 0;
/* vertical rag-right layout */
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 2.5vh;
}
Ardından, kapsayıcıyı 3D alan bağlamı olarak oluşturun ve CSS clamp()
'yi ayarlayın
işlevlerine dikkat edin. Bildirim
kelepçenin orta değerinin özel bir özellik olduğunu unutmayın. Bu --x
ve --y
değerler fare ile üzerine gelindiğinde JavaScript'ten ayarlanır
daha fazla bilgi edindiniz.
.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)
)
)
;
}
Ardından, ziyaret eden kullanıcıda hareket uygunsa tarayıcıya
bu öğenin dönüşümü de
will-change
.
Ayrıca, dönüşümlerde transition
ayarlayarak interpolasyonu etkinleştirin. Bu
fare kartla etkileşime geçtiğinde geçiş gerçekleşir.
doğru ölçebilir. Animasyon, sürekli olarak devam eden bir animasyondur.
gösteren bir 3D alanı gösteren resim,
bileşenle etkileşim kurmuyor olabilir.
@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;
}
}
rotate-y
animasyonu,50%
tarayıcı, 0%
ve 100%
için varsayılan olarak öğenin varsayılan stilini kullanır. Bu
aynı anda başlayıp bitmesi gereken alternatif animasyonların kısaltmasıdır
dokunun. Bu, sonsuz sayıda alternatif animasyonun ifade edilmesi için harika bir yoldur.
@keyframes rotate-y {
50% {
transform: rotateY(15deg) rotateX(-6deg);
}
}
<li>
öğelerinin stil özelliklerini ayarlama
Her liste öğesi (<li>
) düğmeyi ve kenarlık öğelerini içerir. İlgili içeriği oluşturmak için kullanılan
display
stilinin değişmesi nedeniyle öğe
::marker
position
stili
relative
olarak ayarlandığında, yaklaşan düğme sözde öğeleri
otomatik olarak üretir.
.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;
}
<button>
öğelerinin stil özelliklerini ayarlama
Düğmelerin stilini belirlemek zor olabilir. Birçok durum ve etkileşim türü vardır. ortaya çıkarmanıza yardımcı olabilir. Bu düğmeler, dengeleme işlemi nedeniyle hızlı bir şekilde karmaşıklaşıyor yapay öğeler, animasyonlar ve etkileşimler.
İlk <button>
stilleri
Diğer eyaletleri destekleyecek temel stiller aşağıda verilmiştir.
.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;
}
Düğme sözde öğeleri
Düğmenin kenarlıkları geleneksel kenarlıklar değildir, mutlak konumdadır sözde-öğeler olarak tanımlanmıştır.
Bu öğeler, daha önce gördüğümüz 3D perspektifi yerleşik olarak bulunur. Bu sözde öğelerden biri, düğmeden uzağa itilir. önce kullanıcıya yaklaştırın. Bunun etkisi en çok üst ve alt düğmeleri kullanın.
.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 dönüştürme stilleri
Çocukların yer açabilmesi için transform-style
altındaki transform-style
değeri preserve-3d
olarak ayarlandı
z
ekseninde görünürler. transform
, --distance
olarak ayarlandı
Bu özel mülk, üzerine gelindiğinde ve
odak.
.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));
}
}
Koşullu animasyon stilleri
Kullanıcı hareket etmeye izin veriyorsa, düğme, tarayıcıya
dönüşüm mülkü değişime hazır olmalıdır ve
transform
ve background-color
özellikleri. Şu anki
bu altının incelikli, kademeli bir etkiye sahip olduğunu hissettim.
.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 }
}
}
Fareyle üzerine gelme ve odaklanma etkileşim stilleri
Etkileşim animasyonunun amacı,
düz görünen düğme. Bunu, --distance
değişkenini ayarlayarak başarabilirsiniz.
başlangıçta 1px
olacak. Aşağıdaki kod örneğinde gösterilen seçici,
bir cihazın, düğmenin üzerine gelip gelmediğini veya düğmenin
odaklanılmadığından ve etkinleştirilmediğinden emin olun. Bu durumda, CSS'yi kullanarak
takip etmek için:
- Fareyle üzerine gelme arka plan rengini uygulayın.
- Mesafeyi artırın .
- Zıplama yumuşatma efekti ekleyin.
- Sözde öğe geçişlerini bölümlere ayırın.
.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 }
}
}
}
3D perspektif, reduced
hareket tercihi için yine de çok düzgündu.
Üst ve alt öğeler efekti hoş ve ince bir şekilde gösteriyor.
JavaScript'teki küçük geliştirmeler
Arayüz; klavye, ekran okuyucu, oyun kumandası, dokunmatik ekran ve ancak ikisinde de kullanım kolaylığı sağlamak için JavaScript'e oluşturabilirsiniz.
Destekleyici ok tuşları
Sekme tuşu, menüde gezinmenin iyi bir yoludur, ancak yine de
tuş takımı veya kontrol çubuğu. İlgili içeriği oluşturmak için kullanılan
Genellikle GUI için kullanılan roving-ux kitaplığı
Görev arayüzleri, ok tuşlarını bizim için işleyecek. Aşağıdaki kod
.threeD-button-set
içinde odaklamayı ayarlamak ve odağı
düğme alt öğeleri.
import {rovingIndex} from 'roving-ux'
rovingIndex({
element: document.querySelector('.threeD-button-set'),
target: 'button',
})
Fare paralaks etkileşimi
Farenin izlenmesi ve menüyü yatırmanın sağlanması, artırılmış gerçeklik (AR) ve sanal gerçeklik (VR) simülasyonu için tasarlanmıştır. fare yerine sanal işaretçinizin olduğu oyun arayüzleri Öğeler işaretçinin çok farkında olduğunda eğlenceli olabilir.
Bu küçük bir ekstra özellik olduğundan, etkileşimi
Kullanıcının hareket tercihi. Ayrıca, kurulumun bir parçası olarak düğme listesini saklayın
bileşenini querySelector
ile belleğe yükleyin ve öğenin sınırlarını
menuRect
. Karta uygulanan döndürme ofsetini belirlemek için bu sınırları kullanın
farenin konumuna göre değişir.
const menu = document.querySelector('.threeD-button-set')
const menuRect = menu.getBoundingClientRect()
const { matches:motionOK } = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Ardından, farenin x
ve y
konumlarını kabul eden ve
kartı döndürmek için kullanabileceğimiz bir değerdir. Aşağıdaki işlev fareyi kullanır
ne kadar kutup kapladığını bulmayı öğreteceğim. İlgili içeriği oluşturmak için kullanılan
delta değeri, işlevden döndürülür.
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}
}
Son olarak, farenin hareketini izleyin, konumu getAngles()
fonksiyonumuza geçirin
ve delta değerlerini özel mülk stilleri olarak kullanın. Toplamak için 20'ye böltüm
bunu yapmanın daha iyi bir yolu olabilir. Şu durumda:
Hatırladığımızda, --x
ve --y
öğelerini bir oyun odasının
clamp()
işlevi, bu durumda fare konumunun
okunaklı olmayan bir duruma getirin.
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`)
})
}
Çeviriler ve talimatlar
Diğer yazma modlarında oyun menüsünü test ederken bir hata oluştu. dil.
<button>
öğeleri, kullanıcıda writing-mode
için !important
stiline sahip
aracı stil sayfasıdır. Bu da, oyun menüsü HTML'sinin uyumlu olması için değişmesi gerektiği anlamına geliyordu.
tasarlamaya çalışıyor. Düğme listesini bir bağlantı listesine dönüştürmek,
<a>
öğelerinin tarayıcısı olmadığından, menü yönünü değiştirmek için
!important
stili sağlandı.
Sonuç
Şimdi bunu nasıl yaptığımı öğrendiğinize göre nasıl ‽ 🙂 İvme ölçer ekleyebilir misin telefonunuzu döşemek menüyü döndürüyor mu? İyileştirebilir miyiz hareketsiz deneyim mi?
Gelin, yaklaşımlarımızı çeşitlendirelim ve web'de içerik geliştirmenin tüm yollarını öğrenelim. Bir demo oluşturup beni tweet'le bağlantıları eklerim aşağıdaki topluluk remiksleri bölümüne gidin!
Topluluk remiksleri
Henüz burada görülecek bir şey yok.