3D oyun menü bileşeni oluşturma

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.

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.

CANNOT TRANSLATE
öğe olarak normal düğmelerin bulunduğu çok genel görünümlü bir madde işareti listesi.

CSS

Düğme listesinin stilini belirlemek aşağıdaki üst düzey adımlara ayrılır:

  1. Özel özellikleri ayarlama.
  2. Flexbox düzeni.
  3. Dekoratif sözde öğeler içeren özel bir düğme.
  4. Öğ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);
  }
}
Açık ve koyu renk tercihleri arasında değişen arka plan gösterimi.

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;
}

Perspektifi göstermek için listenin ekran görüntüsü 3D alanda döndürüldü ve
her liste öğesinde artık madde işareti yok.

<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;
}

3D perspektifteki düğme listesinin ekran görüntüsü, bu sefer stil özellikleri
düğmelerini kullanın.

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.

Chrome Geliştirici Araçları Elements panelinin ekran görüntüsünde,
::before ve ::sonra öğeleri.

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.
ziyaret edin.
.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.