3D गेम मेन्यू कॉम्पोनेंट बनाना

रिस्पॉन्सिव, अडैप्टिव, और ऐक्सेस किए जा सकने वाले 3D गेम मेन्यू बनाने के तरीके के बारे में बुनियादी जानकारी.

इस पोस्ट में, हम आपको बताना चाहते हैं कि गेम मेन्यू का 3D कॉम्पोनेंट बनाने के बारे में कैसे सोचें. इसे आज़माएं डेमो के लिए उपलब्ध है.

डेमो

अगर आपको वीडियो देखना है, तो इस पोस्ट का YouTube वर्शन यहां देखें:

खास जानकारी

वीडियो गेम में अक्सर उपयोगकर्ताओं को ऐनिमेशन वाला एक क्रिएटिव और असामान्य मेन्यू दिया जाता है और 3D स्पेस में देखा जा सकता है. यह नए एआर/वीआर गेम में लोकप्रिय है, ताकि मेन्यू अंतरिक्ष में तैरते हुए. आज हम इस इफ़ेक्ट की सबसे ज़रूरी चीज़ों को फिर से शामिल करेंगे. हालांकि, उपयोगकर्ताओं के लिए, कमरे में इस्तेमाल होने वाली रंगों की बेहतरीन स्कीम और ठहरने के लिए सुविधाएं उपलब्ध कराई गई हैं जो कम मोशन पसंद करते हैं.

एचटीएमएल

गेम मेन्यू, बटन की सूची होती है. इसे HTML में दिखाने का सबसे अच्छा तरीका यह है अनुसरण करता है:

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

बटन की सूची से, स्क्रीन रीडर टेक्नोलॉजी और JavaScript या CSS के बिना काम करता है.

एक
आइटम के रूप में सामान्य बटन के साथ बहुत सामान्य दिखने वाली बुलेट सूची.

सीएसएस

बटन की सूची का स्टाइल, यहां दिए गए हाई लेवल के चरणों में बंट जाता है:

  1. कस्टम प्रॉपर्टी सेट अप की जा रही हैं.
  2. एक फ़्लेक्सबॉक्स लेआउट.
  3. सजावटी नकली एलिमेंट वाला कस्टम बटन.
  4. एलिमेंट को 3D स्पेस में डालना.

कस्टम प्रॉपर्टी की खास जानकारी

कस्टम प्रॉपर्टी, काम की जानकारी देकर, वैल्यू को अलग करने में मदद करती हैं बार-बार कोड और शेयर करने से बचाते हुए, बिना किसी क्रम वाली दिखने वाली वैल्यू के लिए नाम डालें बच्चों के बीच मूल्य बरकरार रखें.

नीचे सीएसएस वैरिएबल के रूप में सेव की गई मीडिया क्वेरी दी गई हैं. इन्हें कस्टम" भी कहा जाता है मीडिया. ये दुनिया भर में मौजूद हैं और कोड को छोटा और पढ़ने लायक रखने के लिए, अलग-अलग सिलेक्टर में इस्तेमाल किया जाएगा. कॉन्टेंट बनाने गेम मेन्यू कॉम्पोनेंट में मोशन का इस्तेमाल किया जाता है प्राथमिकताएं, सिस्टम रंग स्कीम, और रंग की रेंज क्षमताओं की डिसप्ले.

@custom-media --motionOK (prefers-reduced-motion: no-preference);
@custom-media --dark (prefers-color-scheme: dark);
@custom-media --HDcolor (dynamic-range: high);

ये कस्टम प्रॉपर्टी, कलर स्कीम को मैनेज करती हैं और माउस को होल्ड करती हैं कर्सर घुमाने के लिए, गेम मेन्यू को इंटरैक्टिव बनाने के लिए पोज़िशनल वैल्यू का इस्तेमाल करता है. पसंद के मुताबिक नाम प्रॉपर्टी, कोड को आसानी से पढ़ने में मदद करती हैं, क्योंकि इससे वैल्यू या वैल्यू के नतीजे के लिए दोस्ताना नाम.

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

हल्के और गहरे रंग वाली थीम वाले बैकग्राउंड कोनिक बैकग्राउंड

हल्के रंग वाली थीम में वाइब्रेंट cyan से लेकर deeppink शांकव शामिल है ग्रेडिएंट जबकि गहरे रंग वाली थीम में गहरे रंग का शंकु ग्रेडिएंट मौजूद है. इनके बारे में ज़्यादा जानने के लिए कोनिक ग्रेडिएंट की मदद से सेट अप किया जा सकता है, तो conic.style देखें.

html {
  background: conic-gradient(at -10% 50%, deeppink, cyan);

  @media (--dark) {
    background: conic-gradient(at -10% 50%, #212529, 50%, #495057, #212529);
  }
}
इस इमेज में, हल्के और गहरे रंग की प्राथमिकताओं के बीच बैकग्राउंड बदलते हुए दिखाया गया है.

3D दृश्य चालू करना

वेब पेज की 3D जगह में तत्वों के मौजूद रहने के लिए, एक व्यूपोर्ट खास तौर पर शुरू करना होगा. मैंने body एलिमेंट के लिए ऐंगल रखने का विकल्प चुना है और अपनी पसंद की शैली बनाने के लिए व्यूपोर्ट इकाइयों का इस्तेमाल किया.

body {
  perspective: 40vw;
}

लोगों पर इस तरह का असर पड़ सकता है.

<ul> बटन की सूची का लुक तय किया जा रहा है

यह एलिमेंट बटन की पूरी सूची के मैक्रो लेआउट के साथ-साथ, इसके लिए भी ज़िम्मेदार है जो एक इंटरैक्टिव और 3D फ़्लोटिंग कार्ड है. इसे हासिल करने का तरीका यहां बताया गया है.

बटन ग्रुप का लेआउट

Flexbox, कंटेनर लेआउट को मैनेज कर सकता है. फ़्लेक्स की डिफ़ॉल्ट दिशा बदलें पंक्तियों से लेकर flex-direction वाले कॉलम तक. साथ ही, पक्का करें कि हर आइटम का साइज़ align-items के लिए stretch से start में बदलकर इसकी सामग्री.

.threeD-button-set {
  /* remove <ul> margins */
  margin: 0;

  /* vertical rag-right layout */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2.5vh;
}

इसके बाद, कंटेनर को 3D स्पेस के कॉन्टेक्स्ट के तौर पर सेट करें और सीएसएस clamp() को सेट अप करें फ़ंक्शन यह सुनिश्चित करता है कि कार्ड पठनीय रोटेशन से आगे न घूम जाए. सूचना कि क्लैंप के लिए बीच की वैल्यू एक कस्टम प्रॉपर्टी है, ये --x और --y माउस पर क्लिक करने पर, वैल्यू JavaScript से सेट होंगी इंटरैक्शन बाद में किया जा सकता है.

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

इसके बाद, यदि विज़िट करने वाले उपयोगकर्ता के लिए गति ठीक है, तो ब्राउज़र को एक संकेत जोड़ें कि इस आइटम का रूपांतरण इसके साथ लगातार बदलता रहेगा will-change. इसके अलावा, ट्रांसफ़ॉर्म पर transition सेट करके इंटरपोलेशन चालू करें. यह ट्रांज़िशन तब होगा, जब माउस, कार्ड से इंटरैक्ट करेगा और स्मूद घुमाव में बदलाव किए जाते हैं. यह ऐनिमेशन लगातार चल रहा है जो कार्ड के अंदर के 3D स्पेस को दिखाता है, भले ही माउस ऐसा नहीं कर पाए या कॉम्पोनेंट के साथ इंटरैक्ट नहीं कर रहा है.

@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 ऐनिमेशन सिर्फ़ बीच की कीफ़्रेम को 50% पर सेट करता है ब्राउज़र, 0% और 100% को एलिमेंट की डिफ़ॉल्ट स्टाइल पर सेट कर देगा. यह यह उन एनिमेशन के लिए शॉर्टहैंड है जो वैकल्पिक रूप से एक ही समय पर शुरू और खत्म होते हैं स्थिति. यह अलग-अलग ऐनिमेशन वाले शब्दों को लिखने का एक बेहतरीन तरीका है.

@keyframes rotate-y {
  50% {
    transform: rotateY(15deg) rotateX(-6deg);
  }
}

<li> एलिमेंट का लुक तय करना

सूची के हर आइटम (<li>) में बटन और उसके बॉर्डर एलिमेंट होते हैं. कॉन्टेंट बनाने display स्टाइल बदल दी गई है, इसलिए आइटम ::marker. position स्टाइल relative पर सेट है, ताकि आने वाले बटन pseudo-elements सही जगह पर सेट हो सकें उसके द्वारा बटन का उपयोग किए जाने वाले पूरे क्षेत्र में मौजूद हों.

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

ऐंगल दिखाने के लिए, सूची का स्क्रीनशॉट 3D स्पेस में घुमाया गया और
सूची के हर आइटम में अब बुलेट नहीं है.

<button> एलिमेंट का लुक तय करना

बटनों को शैली देना काफ़ी मुश्किल काम है. अलग-अलग स्थितियों और इंटरैक्शन के तरीके अलग-अलग होते हैं लेख पढ़ें. इन बटनों को संतुलित करने की वजह से, ये बटन जल्दी जटिल हो जाते हैं नकली-एलिमेंट, ऐनिमेशन और इंटरैक्शन.

शुरुआती <button> स्टाइल

यहां कुछ बुनियादी स्टाइल दिए गए हैं, जो दूसरे राज्यों के लिए भी मददगार होंगे.

.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 व्यू का स्क्रीनशॉट, अब स्टाइल के साथ
बटन.

बटन के नकली एलिमेंट

बटन के बॉर्डर, पारंपरिक बॉर्डर नहीं हैं. ये बॉर्डर पूरे पोज़िशन में हैं बॉर्डर वाले छद्म-एलिमेंट.

Chrome Devtools के एलिमेंट पैनल का स्क्रीनशॉट, जिसमें एक बटन दिख रहा है
::पहले और ::बाद एलिमेंट.

ये तत्व उस 3D दृश्य को प्रदर्शित करने के लिए महत्वपूर्ण हैं जो स्थापित किया गया. इनमें से किसी एक नकली एलिमेंट को बटन से हटा दिया जाएगा, इनमें से एक को उपयोगकर्ता के ज़्यादा करीब लाया जाएगा. यह इफ़ेक्ट सबसे ज़्यादा नज़र आता है ऊपर और नीचे वाले बटन.

.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 ट्रांसफ़ॉर्म स्टाइल

transform-style से नीचे की वैल्यू को preserve-3d पर सेट किया गया है, ताकि बच्चे स्पेस में शामिल हो सकें खुद को z ऐक्सिस पर बाहर किया है. transform को --distance पर सेट किया गया है कस्टम प्रॉपर्टी होगी, जो होवर और फ़ोकस.

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

कंडिशनल ऐनिमेशन स्टाइल

यदि उपयोगकर्ता गति के साथ ठीक है, तो बटन ब्राउज़र को यह संकेत देता है कि ट्रांसफ़ॉर्म प्रॉपर्टी में बदलाव किया जा सकता है और इसके लिए ट्रांज़िशन सेट किया गया है transform और background-color प्रॉपर्टी. इसमें अंतर देखें अवधि के दौरान, मुझे लगा कि यह एक अच्छे बदलाव के साथ बनाया गया है.

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

इंटरैक्शन स्टाइल पर कर्सर घुमाएं और उन पर फ़ोकस करें

इंटरैक्शन ऐनिमेशन का मकसद, लेयर बनाने वाली लेयर को फैलाना है दिखने वाला फ़्लैट बटन. --distance वैरिएबल को सेट करके, इस लक्ष्य को पूरा करें शुरुआती कीमत 1px थी. कोड के इस उदाहरण में दिखाया गया सिलेक्टर, इन चीज़ों की जांच करता है: देखें कि क्या बटन को किसी ऐसे डिवाइस पर घुमाया जा रहा है या उस पर फ़ोकस किया जा रहा है जिसे फ़ोकस इंंडिकेटर है और चालू नहीं किया जा रहा है. अगर ऐसा है, तो यह फ़ॉलो किया जा रहा है:

  • होवर बैकग्राउंड का रंग लागू करें.
  • दूरी बढ़ाएं .
  • बाउंस ईज़िंग इफ़ेक्ट जोड़ें.
  • स्यूडो एलिमेंट ट्रांज़िशन को अडजस्ट करें.
.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 }
    }
  }
}

reduced की मोशन प्राथमिकता के लिए, 3D व्यू सटीक था. ऊपर और नीचे के एलिमेंट, इफ़ेक्ट को अच्छे से दिखाते हैं.

JavaScript की मदद से छोटे-छोटे सुधार

इस इंटरफ़ेस का इस्तेमाल कीबोर्ड, स्क्रीन रीडर, गेमपैड, टच और माउस पहले से ही, लेकिन हम कुछ आसान बनाने के लिए JavaScript की कुछ सुविधाएं जोड़ सकते हैं. सकता है.

तीर के निशान वाली कुंजियां

Tab बटन, मेन्यू को नेविगेट करने का एक अच्छा तरीका है. हालांकि, यह एक बेहतर विकल्प है, गेमपैड पर फ़ोकस मूव करने के लिए पैड या जॉयस्टिक का इस्तेमाल करें. कॉन्टेंट बनाने roving-ux लाइब्रेरी का इस्तेमाल अक्सर जीयूआई के लिए किया जाता है चैलेंज इंटरफ़ेस हमारे लिए तीर कुंजियों का इस्तेमाल करेगा. नीचे दिया गया कोड, .threeD-button-set में फ़ोकस बनाए रखने और फ़ोकस को आगे बढ़ाने के लिए बटन चिल्ड्रन.

import {rovingIndex} from 'roving-ux'

rovingIndex({
  element: document.querySelector('.threeD-button-set'),
  target: 'button',
})

माउस पैरालक्स इंटरैक्शन

एआर और वीआर की नकल करने के मकसद से माउस को ट्रैक करना और मेन्यू को झुकाना ऐसे वीडियो गेम इंटरफ़ेस होते हैं जिनमें माउस के बजाय, एक वर्चुअल पॉइंटर हो सकता है. यह मज़ेदार हो सकता है, जब एलिमेंट को पॉइंटर के बारे में पूरी जानकारी हो.

यह एक छोटी सी सुविधा है, इसलिए हम इंटरैक्शन को उपयोगकर्ता की मोशन प्राथमिकता. साथ ही, सेटअप के दौरान बटन की सूची को सेव करें querySelector के साथ कॉम्पोनेंट को मेमोरी में सेव करना और एलिमेंट की बाउंड्री को कैश मेमोरी में सेव करना menuRect. कार्ड पर लागू किए गए घूमने ऑफ़सेट को तय करने के लिए इन सीमाओं का उपयोग करें जो कि माउस की स्थिति के हिसाब से तय होता है.

const menu = document.querySelector('.threeD-button-set')
const menuRect = menu.getBoundingClientRect()

const { matches:motionOK } = window.matchMedia(
  '(prefers-reduced-motion: no-preference)'
)

इसके बाद, हमें एक ऐसे फ़ंक्शन की ज़रूरत है जो माउस के x और y पोज़िशन और रिटर्न को स्वीकार कर सके वह वैल्यू होती है जिसे हम कार्ड को घुमाने के लिए इस्तेमाल कर सकते हैं. निम्न फ़ंक्शन माउस का उपयोग करता है इससे पता लगाया जा सकता है कि यह बॉक्स के किस हिस्से में है और कितनी जगह पर है. कॉन्टेंट बनाने डेल्टा को फ़ंक्शन से वापस लाया जाता है.

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

आखिर में, माउस की मदद से मूव करें और इस पोज़िशन को हमारे getAngles() फ़ंक्शन पर पास करें और डेल्टा वैल्यू का इस्तेमाल कस्टम प्रॉपर्टी स्टाइल के तौर पर करें. इसे पैड पर सेट करने के लिए, मुझे 20 से भाग देना डेल्टा और घबराहट कम करें, तो ऐसा करने का एक बेहतर तरीका हो सकता है. अगर आपको शुरुआत से याद रखना होगा, हम --x और --y प्रॉप्स को वीडियो के बीच में clamp() फ़ंक्शन का इस्तेमाल करता है, तो यह माउस की स्थिति को कार्ड में मौजूद कार्ड अस्पष्ट स्थान पर रखना चाहिए.

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`)
  })
}

अनुवाद और दिशा-निर्देश

गेम मेन्यू को अन्य राइटिंग मोड में टेस्ट करने पर, मुझे एक परेशानी नज़र आई और भाषाएं.

उपयोगकर्ता में writing-mode के लिए, <button> एलिमेंट की स्टाइल !important है एजेंट स्टाइलशीट. इसका मतलब था कि गेम मेन्यू के एचटीएमएल को अडजस्ट करने के लिए, डिज़ाइन करना होगा. बटन सूची को लिंक की सूची में बदलने से लॉजिकल चालू होता है प्रॉपर्टी मेन्यू की दिशा बदलने के लिए सेट की जा सकती हैं, क्योंकि <a> एलिमेंट में ब्राउज़र मौजूद नहीं है !important शैली की सप्लाई की गई.

नतीजा

अब जब आपको पता है कि मैंने इसे कैसे किया, तो आप कैसे करेंगे‽ 🙂 क्या आप एक्सलरोमीटर जोड़ सकते हैं इंटरैक्शन करते हैं, तो आपके फ़ोन पर टाइल लगाने से मेन्यू बदल जाता है? क्या हम इसे बेहतर बना सकते हैं का इस्तेमाल नहीं कर पा रहे हैं?

आइए, हम अलग-अलग तरह के काम करते हैं और वेब पर काम करने के सभी तरीके सीखते हैं. एक डेमो बनाएं, मुझे ट्वीट करें और मैं इसे जोड़ दूंगा कम्यूनिटी रीमिक्स बनाने के लिए यहां दिए गए सेक्शन पर जाएं!

कम्यूनिटी रीमिक्स

फ़िलहाल, यहां कोई कॉन्टेंट मौजूद नहीं है!