स्विच कॉम्पोनेंट बनाना

रिस्पॉन्सिव और ऐक्सेस किए जा सकने वाले स्विच कॉम्पोनेंट बनाने के तरीके के बारे में खास जानकारी.

इस पोस्ट में, हम आपको बताना चाहते हैं कि स्विच कॉम्पोनेंट को कैसे तैयार किया जाता है. डेमो देखें.

डेमो

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

खास जानकारी

चेकबॉक्स की तरह ही स्विच भी काम करता है लेकिन यह साफ़ तौर पर बूलियन ऑन और ऑफ़ स्टेट को दिखाता है.

यह डेमो, अपने ज़्यादातर वीडियो के लिए <input type="checkbox" role="switch"> का इस्तेमाल करता है इसके लिए, सीएसएस या JavaScript की ज़रूरत नहीं होती वे पूरी तरह से काम कर रहे हों और आसानी से ऐक्सेस कर सकें. सीएसएस को लोड करने से, दाईं से बाईं ओर के लिए सहायता मिलती है भाषाएं, वर्टिकलिटी, ऐनिमेशन वगैरह. JavaScript लोड होने से साइट पर खींचने और छोड़ने लायक हों.

कस्टम प्रॉपर्टी

नीचे दिए गए वैरिएबल, स्विच के अलग-अलग हिस्सों और उनके के विकल्प. टॉप-लेवल क्लास के तौर पर, .gui-switch में इस्तेमाल की गई कस्टम प्रॉपर्टी शामिल हैं कॉम्पोनेंट चिल्ड्रेन और एक ही जगह से सब मैनेज करने के लिए एंट्री पॉइंट पसंद के मुताबिक बनाने की सुविधा मिलती है.

ट्रैक

लंबाई (--track-size), पैडिंग, और दो रंग:

.gui-switch {
  --track-size: calc(var(--thumb-size) * 2);
  --track-padding: 2px;

  --track-inactive: hsl(80 0% 80%);
  --track-active: hsl(80 60% 45%);

  --track-color-inactive: var(--track-inactive);
  --track-color-active: var(--track-active);

  @media (prefers-color-scheme: dark) {
    --track-inactive: hsl(80 0% 35%);
    --track-active: hsl(80 60% 60%);
  }
}

थंब

साइज़, बैकग्राउंड का रंग, और इंटरैक्शन को हाइलाइट करने वाले रंग:

.gui-switch {
  --thumb-size: 2rem;
  --thumb: hsl(0 0% 100%);
  --thumb-highlight: hsl(0 0% 0% / 25%);

  --thumb-color: var(--thumb);
  --thumb-color-highlight: var(--thumb-highlight);

  @media (prefers-color-scheme: dark) {
    --thumb: hsl(0 0% 5%);
    --thumb-highlight: hsl(0 0% 100% / 25%);
  }
}

कम मोशन

साफ़ उपनाम जोड़ने और दोहराव को कम करने के लिए, कम मोशन प्राथमिकता वाला उपयोगकर्ता मीडिया क्वेरी को पोस्टसीएसएस की मदद से कस्टम प्रॉपर्टी में रखा जा सकता है इस ड्राफ़्ट पर आधारित प्लगिन मीडिया क्वेरी में खास जानकारी 5:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

मार्कअप

मैंने अपने <input type="checkbox" role="switch"> एलिमेंट को <label>, चेकबॉक्स और लेबल को असोसिएट होने से रोकने के लिए, अपने संबंधों को बंडल कर रहा है साफ़ तौर पर जानकारी देता है. साथ ही, इससे उपयोगकर्ता को लेबल से इंटरैक्ट करने की अनुमति मिलती है, इनपुट को टॉगल करें.

ऐप्लिकेशन
बिना शैली वाला लेबल और चेकबॉक्स.

<label for="switch" class="gui-switch">
  Label text
  <input type="checkbox" role="switch" id="switch">
</label>

<input type="checkbox"> में, पहले से ही एपीआई और राज्य दिखेगा. कॉन्टेंट बनाने ब्राउज़र, आपकी checked प्रॉपर्टी और इनपुट इवेंट जैसे कि oninputऔर onchanged.

लेआउट

फ़्लेक्सबॉक्स, ग्रिड और कस्टम प्रॉपर्टी ज़रूरी हैं, इस कॉम्पोनेंट की स्टाइल को बनाए रखने के लिए किया जा सकता है. वे एक ही जगह पर मानों को रखते हैं, और नामों को और छोटे कस्टम प्रॉपर्टी को चालू कर सकते हैं. घटक को आसानी से कस्टमाइज़ करने के लिए API.

.gui-switch

स्विच के लिए टॉप-लेवल लेआउट फ़्लेक्सबॉक्स है. क्लास .gui-switch में यह शामिल है वे निजी और सार्वजनिक कस्टम प्रॉपर्टी जिनका इस्तेमाल करके बच्चा अपनी प्रॉपर्टी का हिसाब लगाता है लेआउट.

Flexbox DevTools, जो हॉरिज़ॉन्टल लेबल और स्विच को ओवरले कर रहा है और उनका लेआउट दिखा रहा है
स्पेस का डिस्ट्रिब्यूशन.

.gui-switch {
  display: flex;
  align-items: center;
  gap: 2ch;
  justify-content: space-between;
}

फ़्लेक्सबॉक्स लेआउट को बढ़ाना और उसमें बदलाव करना, किसी फ़्लेक्सबॉक्स लेआउट को बदलने जैसा है. उदाहरण के लिए, लेबल को किसी स्विच के ऊपर या नीचे रखने के लिए, flex-direction:

वर्टिकल लेबल और स्विच को ओवरले करने वाला Flexbox DevTools.

<label for="light-switch" class="gui-switch" style="flex-direction: column">
  Default
  <input type="checkbox" role="switch" id="light-switch">
</label>

ट्रैक

चेकबॉक्स इनपुट को स्विच ट्रैक के तौर पर सेट किया गया है. इसके लिए, इसे सामान्य बटन से हटा दिया गया है appearance: checkbox और इसके बजाय इसका खुद का साइज़ सप्लाई कर रहा है:

ग्रिड DevTools, स्विच ट्रैक को ओवरले कर रहा है, जिसमें नाम वाला ग्रिड ट्रैक दिख रहा है
&#39;track&#39; नाम के क्षेत्र हैं.

.gui-switch > input {
  appearance: none;

  inline-size: var(--track-size);
  block-size: var(--thumb-size);
  padding: var(--track-padding);

  flex-shrink: 0;
  display: grid;
  align-items: center;
  grid: [track] 1fr / [track] 1fr;
}

ट्रैक, अंगूठे के लिए एक-एक करके सिंगल सेल ग्रिड ट्रैक एरिया भी बनाता है दावा.

थंब

यह शैली appearance: none से दिए गए विज़ुअल सही के निशान को भी हटा देती है ब्राउज़र खोलें. यह कॉम्पोनेंट किसी pseudo-element और :checked इसके इनपुट पर pseudo-class इस विज़ुअल इंडिकेटर को बदलें.

अंगूठा एक स्यूडो-एलिमेंट चाइल्ड है, जो input[type="checkbox"] से जुड़ा हुआ है और ग्रिड एरिया पर दावा करके, ट्रैक के नीचे की जगह पर स्टैक track:

DevTools नकली एलिमेंट थंब को सीएसएस ग्रिड के अंदर पोज़िशन के तौर पर दिखा रहा है.

.gui-switch > input::before {
  content: "";
  grid-area: track;
  inline-size: var(--thumb-size);
  block-size: var(--thumb-size);
}

स्टाइल

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

स्विच के लिए हल्के और गहरे रंग वाली थीम की साथ-साथ तुलना
राज्य.

टच इंटरैक्शन स्टाइल

मोबाइल पर, ब्राउज़र लेबल और टेक्स्ट में, टैप हाइलाइट और टेक्स्ट चुनने की सुविधाएं जोड़ते हैं इनपुट. इससे स्टाइल और विज़ुअल इंटरैक्शन के बारे में मिले सुझावों पर बुरा असर पड़ा इस स्विच की ज़रूरत है. सीएसएस की कुछ लाइनों की मदद से, उन इफ़ेक्ट को हटाया जा सकता है और मेरी अपनी cursor: pointer शैली:

.gui-switch {
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

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

ट्रैक

इस एलिमेंट की स्टाइल, ज़्यादातर इसके आकार और रंग पर आधारित होती है. इससे एलिमेंट को ऐक्सेस किया जा सकता है इसके ज़रिए, पैरंट .gui-switch से कैस्केड.

कस्टम ट्रैक साइज़ और रंगों वाले स्विच के वैरिएंट.

.gui-switch > input {
  appearance: none;
  border: none;
  outline-offset: 5px;
  box-sizing: content-box;

  padding: var(--track-padding);
  background: var(--track-color-inactive);
  inline-size: var(--track-size);
  block-size: var(--thumb-size);
  border-radius: var(--track-size);
}

स्विच ट्रैक को मनमुताबिक बनाने के लिए, चार तरह के विकल्प उपलब्ध हैं कस्टम प्रॉपर्टी. border: none जोड़ा गया है, क्योंकि appearance: none यह नहीं करता सभी ब्राउज़र पर चेकबॉक्स से बॉर्डर निकाल दें.

थंब

अंगूठे का एलिमेंट पहले से ही दाईं ओर मौजूद है track, लेकिन इसके लिए सर्कल स्टाइल की ज़रूरत है:

.gui-switch > input::before {
  background: var(--thumb-color);
  border-radius: 50%;
}

DevTools से पता चलता है कि सर्कल थंब pseudo-element को हाइलाइट किया गया है.

बातचीत

कस्टम प्रॉपर्टी का इस्तेमाल ऐसे इंटरैक्शन के लिए करना जिनमें कर्सर घुमाना शामिल है हाइलाइट और अंगूठे की स्थिति में बदलाव. उपयोगकर्ता की प्राथमिकता यह भी है को बदलने से पहले चेक किया हाइलाइट शैलियां हैं या उन्हें मोशन या होवर किया जा सकता है.

.gui-switch > input::before {
  box-shadow: 0 0 0 var(--highlight-size) var(--thumb-color-highlight);

  @media (--motionOK) { & {
    transition:
      transform var(--thumb-transition-duration) ease,
      box-shadow .25s ease;
  }}
}

पसंद की जगह

कस्टम प्रॉपर्टी में, अंगूठे को सही जगह पर रखने के लिए एक ही सोर्स मैकेनिज़्म होता है ट्रैक करें. हमारे लिए यहां ट्रैक और थंब साइज़ दिए गए हैं, जिनका इस्तेमाल हम अंगूठे को ट्रैक के अंदर और बीच में ठीक तरह से ऑफ़सेट रखने के लिए कैलकुलेशन: 0% और 100%.

input एलिमेंट के पास पोज़िशन वैरिएबल --thumb-position और अंगूठे का मालिकाना हक है pseudo एलिमेंट इसका इस्तेमाल translateX पोज़िशन के तौर पर करता है:

.gui-switch > input {
  --thumb-position: 0%;
}

.gui-switch > input::before {
  transform: translateX(var(--thumb-position));
}

अब हम --thumb-position को सीएसएस और pseudo-classes से बदल सकते हैं यह सुविधा, चेकबॉक्स एलिमेंट पर दी गई है. हमने इस एलिमेंट पर, शर्तों के साथ transition: transform var(--thumb-transition-duration) ease को पहले सेट किया था. इसलिए, ये बदलाव हुए हैं बदलाव किए जाने पर ऐनिमेट हो सकता है:

/* positioned at the end of the track: track length - 100% (thumb width) */
.gui-switch > input:checked {
  --thumb-position: calc(var(--track-size) - 100%);
}

/* positioned in the center of the track: half the track - half the thumb */
.gui-switch > input:indeterminate {
  --thumb-position: calc(
    (var(--track-size) / 2) - (var(--thumb-size) / 2)
  );
}

मुझे लगा कि अलग-अलग ऑर्केस्ट्रा का यह कलेक्शन काफ़ी कारगर साबित हुआ. अंगूठा तत्व है सिर्फ़ एक शैली, translateX स्थिति से संबंधित है. इनपुट से सभी को मैनेज किया जा सकता है और कैलकुलेशन की ज़रूरत होती है.

वर्टिकल

सपोर्ट करने की सुविधा, कार्रवाई बदलने वाली क्लास -vertical की मदद से दी गई. इससे, कार्रवाई के साथ एक रोटेशन जुड़ जाता है सीएसएस, input एलिमेंट में बदल जाता है.

हालांकि, 3D घुमाए गए एलिमेंट से कॉम्पोनेंट की कुल ऊंचाई में कोई बदलाव नहीं होता, जो ब्लॉक लेआउट को बंद कर सकते हैं. --track-size और --track-padding वैरिएबल. इसके लिए आवश्यक कम से कम स्थान की गणना करें लेआउट में फ़्लो करने के लिए वर्टिकल बटन:

.gui-switch.-vertical {
  min-block-size: calc(var(--track-size) + calc(var(--track-padding) * 2));

  & > input {
    transform: rotate(-90deg);
  }
}

(RTL) दाएं से बाएं

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

.gui-switch {
  --isLTR: 1;

  &:dir(rtl) {
    --isLTR: -1;
  }
}

--isLTR नाम की कस्टम प्रॉपर्टी में शुरू में 1 का मान होता है, जिसका मतलब यह है true क्योंकि हमारा लेआउट डिफ़ॉल्ट रूप से बाएं-से-दाएं होता है. इसके बाद, सीएसएस का इस्तेमाल करके सूडो क्लास :dir(), कॉम्पोनेंट के दाएं से बाएं लेआउट में होने पर, वैल्यू -1 पर सेट होती है.

किसी ट्रांसफ़ॉर्म के अंदर calc() में --isLTR का इस्तेमाल करके, इसे चालू करें:

.gui-switch.-vertical > input {
  transform: rotate(-90deg);
  transform: rotate(calc(90deg * var(--isLTR) * -1));
}

अब वर्टिकल स्विच को दूसरी तरफ़ की स्थिति के हिसाब से घुमाया जाता है दाईं से बाईं ओर के लेआउट के लिए ज़रूरी है.

थंब स्यूडो-एलिमेंट में translateX में होने वाले बदलाव को भी अपडेट करना ज़रूरी है सेवा की शर्तों को पूरा करें:

.gui-switch > input:checked {
  --thumb-position: calc(var(--track-size) - 100%);
  --thumb-position: calc((var(--track-size) - 100%) * var(--isLTR));
}

.gui-switch > input:indeterminate {
  --thumb-position: calc(
    (var(--track-size) / 2) - (var(--thumb-size) / 2)
  );
  --thumb-position: calc(
   ((var(--track-size) / 2) - (var(--thumb-size) / 2))
    * var(--isLTR)
  );
}

हालांकि, इस तरीके से लॉजिकल सीएसएस जैसे कॉन्सेप्ट की सभी ज़रूरतों को पूरा नहीं किया जा सकता पूरी तरह से बदल देता है, लेकिन यह कुछ कई लोगों के लिए, DRY के सिद्धांत इस्तेमाल के उदाहरण.

राज्य

बिल्ट-इन input[type="checkbox"] का इस्तेमाल इसके बिना पूरा नहीं होगा यह उन अलग-अलग राज्यों को हैंडल करता है जहां यह हो सकता है: :checked, :disabled, :indeterminate और :hover. :focus को जान-बूझकर अकेला छोड़ा गया था. इसमें जो सिर्फ़ अपने ऑफ़सेट पर किए गए हैं; फ़ोकस रिंग, Firefox पर बहुत बढ़िया लग रही थी और सफ़ारी:

Firefox और Safari में एक स्विच पर फ़ोकस किए गए फ़ोकस रिंग का स्क्रीनशॉट.

सही का निशान लगाया गया

<label for="switch-checked" class="gui-switch">
  Default
  <input type="checkbox" role="switch" id="switch-checked" checked="true">
</label>

यह राज्य, on राज्य को दिखाता है. इस स्थिति में, इनपुट "track" बैकग्राउंड चालू रंग पर और अंगूठे की पोज़िशन " एंड".

.gui-switch > input:checked {
  background: var(--track-color-active);
  --thumb-position: calc((var(--track-size) - 100%) * var(--isLTR));
}

बंद है

<label for="switch-disabled" class="gui-switch">
  Default
  <input type="checkbox" role="switch" id="switch-disabled" disabled="true">
</label>

:disabled बटन सिर्फ़ देखने में अलग नहीं दिखता, बल्कि एलिमेंट को नहीं बदला जा सकता.ब्राउज़र में इंटरैक्शन नहीं करने की सुविधा मुफ़्त है, लेकिन appearance: none के इस्तेमाल की वजह से विज़ुअल स्थितियों को स्टाइल की ज़रूरत है.

.gui-switch > input:disabled {
  cursor: not-allowed;
  --thumb-color: transparent;

  &::before {
    cursor: not-allowed;
    box-shadow: inset 0 0 0 2px hsl(0 0% 100% / 50%);

    @media (prefers-color-scheme: dark) { & {
      box-shadow: inset 0 0 0 2px hsl(0 0% 0% / 50%);
    }}
  }
}

गहरे रंग वाला स्विच बंद है, सही का निशान लगा है, और सही का निशान नहीं लगाया गया है
राज्य.

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

तय नहीं किया जा सका

अक्सर भूलने वाली स्थिति :indeterminate होती है, जहां चेकबॉक्स दोनों में से कोई नहीं होता चुना गया या उससे सही का निशान हटाया गया है. यह एक मज़ेदार स्थिति है, यह लुभावने और साधारण है. बहुत अच्छा ध्यान रखें कि दो राज्यों के बीच बूलियन स्टेट स्नीकी हो सकते हैं.

चेकबॉक्स को तय नहीं करना मुश्किल है, सिर्फ़ JavaScript इसे सेट कर सकता है:

<label for="switch-indeterminate" class="gui-switch">
  Indeterminate
  <input type="checkbox" role="switch" id="switch-indeterminate">
  <script>document.getElementById('switch-indeterminate').indeterminate = true</script>
</label>

यह ऐसी अनिश्चित स्थिति है जिसमें ट्रैक थंब
बीच में.

चूंकि राज्य मेरे लिए सादगी भरा और आमंत्रित है, इसलिए इस बीच में स्विच अंगूठे की स्थिति:

.gui-switch > input:indeterminate {
  --thumb-position: calc(
    calc(calc(var(--track-size) / 2) - calc(var(--thumb-size) / 2))
    * var(--isLTR)
  );
}

कर्सर घुमाएं

होवर इंटरैक्शन को कनेक्ट किए गए यूज़र इंटरफ़ेस (यूआई) के लिए विज़ुअल सपोर्ट देना चाहिए. साथ ही, इंटरैक्टिव यूज़र इंटरफ़ेस (यूआई) के बारे में जानकारी देता है. यह स्विच इसके साथ अंगूठे को हाइलाइट करता है लेबल या इनपुट पर कर्सर घुमाने पर, आधा-पारदर्शी रिंग होता है. यह होवर इसके बाद ऐनिमेशन, इंटरैक्टिव थंब एलिमेंट के बारे में बताता है.

"हाइलाइट" इफ़ेक्ट box-shadow के साथ किया गया. कर्सर घुमाने पर, बंद नहीं किए गए इनपुट के लिए --highlight-size का साइज़ बढ़ाएं. अगर उपयोगकर्ता को मोशन से जुड़ी कोई समस्या नहीं है, तो हम box-shadow का ट्रांज़िशन करके इसे बढ़ाएंगे. अगर उनमें गति ठीक नहीं होती, तो हाइलाइट तुरंत दिखने लगती है:

.gui-switch > input::before {
  box-shadow: 0 0 0 var(--highlight-size) var(--thumb-color-highlight);

  @media (--motionOK) { & {
    transition:
      transform var(--thumb-transition-duration) ease,
      box-shadow .25s ease;
  }}
}

.gui-switch > input:not(:disabled):hover::before {
  --highlight-size: .5rem;
}

JavaScript

मुझे लगता है कि स्विच इंटरफ़ेस किसी फ़िज़िकल प्रोसेस को टेस्ट करने के लिए, विशेष रूप से इस प्रकार के इंटरफ़ेस में एक सर्कल बना होता है. iOS ने यह सही जवाब दिया साथ ही, उन्हें एक-दूसरे से खींचकर दूसरी तरफ़ ले जाया जा सकता है. इससे अच्छा अनुभव मिलता है कि का विकल्प है. इसके उलट, अगर खींचकर छोड़ने का जेस्चर काम नहीं करता है, तो यूआई एलिमेंट काम नहीं कर रहा कोशिश की गई, लेकिन कुछ नहीं हुआ.

खींचने योग्य थंब्स

अंगूठे के छद्म एलिमेंट को .gui-switch > input से अपनी पोज़िशन मिलती है var(--thumb-position) के दायरे में, JavaScript एक इनलाइन स्टाइल वैल्यू दे सकता है थंब पोज़िशन को डाइनैमिक तौर पर अपडेट करने के लिए इनपुट. इससे ऐसा लगता है कि पॉइंटर जेस्चर का इस्तेमाल करें. पॉइंटर रिलीज़ होने पर, इनलाइन स्टाइल हटा दें और कस्टम प्रॉपर्टी का इस्तेमाल करके यह पता लगाएं कि ड्रैग की प्रोसेस बंद थी या चालू थी --thumb-position. यह घोल का आधार है; पॉइंटर इवेंट सीएसएस कस्टम प्रॉपर्टी में बदलाव करने के लिए, पॉइंटर की पोज़िशन को ट्रैक करना.

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

touch-action

खींचें और छोड़ें, एक जेस्चर है, जो इसे पसंद के मुताबिक बनाया जाता है. इस वजह से यह जेस्चर, touch-action के फ़ायदे. इस स्विच के मामले में, हॉरिज़ॉन्टल जेस्चर को उसे हमारी स्क्रिप्ट से हैंडल किया जाएगा या वर्टिकल स्विच के लिए कैप्चर किया गया वर्टिकल जेस्चर वैरिएंट. touch-action की मदद से हम ब्राउज़र को बता सकते हैं कि हाथ के किन जेस्चर का इस्तेमाल करना है इस एलिमेंट की मदद से, स्क्रिप्ट बिना किसी प्रतिस्पर्धा के जेस्चर को हैंडल कर सकती है.

नीचे दिया गया सीएसएस, ब्राउज़र को निर्देश देता है कि जब पॉइंटर जेस्चर शुरू होता है इस स्विच ट्रैक में, वर्टिकल जेस्चर हैंडल करें, हॉरिज़ॉन्टल वाला कुछ भी न करें इनमें शामिल हैं:

.gui-switch > input {
  touch-action: pan-y;
}

जो नतीजा मिलता है वह एक हॉरिज़ॉन्टल जेस्चर होता है जो पेज के जेस्चर को पैन या स्क्रोल नहीं करता करें. पॉइंटर इनपुट में से वर्टिकल तौर पर स्क्रोल करके, नीचे की ओर स्क्रोल करके पेज, लेकिन हॉरिज़ॉन्टल मैन्युअल तौर पर हैंडल किए जाते हैं.

Pixel वैल्यू की स्टाइल से जुड़ी सुविधाएं

सेटअप करने के दौरान और खींचकर छोड़ने के दौरान, कंप्यूट की गई संख्या की अलग-अलग वैल्यू को पता करना होगा एलिमेंट से निकाल दिया जाता है. यहां दिए गए JavaScript फ़ंक्शन, कंप्यूट किए गए पिक्सल वैल्यू दिखाते हैं को सीएसएस प्रॉपर्टी दी गई है. इसका इस्तेमाल सेटअप स्क्रिप्ट में इस तरह किया जाता है getStyle(checkbox, 'padding-left').

​​const getStyle = (element, prop) => {
  return parseInt(window.getComputedStyle(element).getPropertyValue(prop));
}

const getPseudoStyle = (element, prop) => {
  return parseInt(window.getComputedStyle(element, ':before').getPropertyValue(prop));
}

export {
  getStyle,
  getPseudoStyle,
}

ध्यान दें कि window.getComputedStyle() किस तरह दूसरे आर्ग्युमेंट, टारगेट pseudo एलिमेंट को स्वीकार करता है. इस बात की अच्छी बात है कि JavaScript, एलिमेंट के कई वैल्यू पढ़ सकता है. यहां तक कि pseudo एलिमेंट से भी.

dragging

यह ड्रैग लॉजिक के लिए एक खास पल है और कुछ बातों का ध्यान रखना होगा फ़ंक्शन इवेंट हैंडलर से:

const dragging = event => {
  if (!state.activethumb) return

  let {thumbsize, bounds, padding} = switches.get(state.activethumb.parentElement)
  let directionality = getStyle(state.activethumb, '--isLTR')

  let track = (directionality === -1)
    ? (state.activethumb.clientWidth * -1) + thumbsize + padding
    : 0

  let pos = Math.round(event.offsetX - thumbsize / 2)

  if (pos < bounds.lower) pos = 0
  if (pos > bounds.upper) pos = bounds.upper

  state.activethumb.style.setProperty('--thumb-position', `${track + pos}px`)
}

स्क्रिप्ट हीरो state.activethumb है, जो कि इस स्क्रिप्ट का छोटा गोला है पॉइंटर के साथ पोज़िशनिंग करें. switches ऑब्जेक्ट एक Map() है, जहां कुंजियां .gui-switch की हैं और वैल्यू, कैश मेमोरी में सेव की गई सीमाएं और साइज़ हैं, जो सही तरीके से काम किया है. दाएं से बाएं हैंडल को एक ही कस्टम प्रॉपर्टी का इस्तेमाल करके हैंडल किया जाता है वह सीएसएस --isLTR है. साथ ही, वह लॉजिक को उलटा करने और जारी रखने के लिए इसका इस्तेमाल कर सकती है RTL का समर्थन करना. event.offsetX भी अहम है, क्योंकि इसमें डेल्टा है अंगूठे को सही जगह पर रखने के लिए उपयोगी मान है.

state.activethumb.style.setProperty('--thumb-position', `${track + pos}px`)

सीएसएस की यह आखिरी लाइन, थंब एलिमेंट में इस्तेमाल की जाने वाली कस्टम प्रॉपर्टी सेट करती है. यह वैल्यू असाइनमेंट समय के साथ ट्रांज़िशन होगा, लेकिन एक पिछला पॉइंटर इवेंट ने --thumb-transition-duration को कुछ समय के लिए 0s पर सेट कर दिया है. यह इवेंट हटा दिया गया है एक सुस्त इंटरैक्शन होता.

dragEnd

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

window.addEventListener('pointerup', event => {
  if (!state.activethumb) return

  dragEnd(event)
})

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

const dragEnd = event => {
  if (!state.activethumb) return

  state.activethumb.checked = determineChecked()

  if (state.activethumb.indeterminate)
    state.activethumb.indeterminate = false

  state.activethumb.style.removeProperty('--thumb-transition-duration')
  state.activethumb.style.removeProperty('--thumb-position')
  state.activethumb.removeEventListener('pointermove', dragging)
  state.activethumb = null

  padRelease()
}

एलिमेंट के साथ इंटरैक्शन पूरा हो गया है. इनपुट को सेट करने का समय हो गया है प्रॉपर्टी चुनने और जेस्चर से जुड़े सभी इवेंट को हटाने का तरीका. चेकबॉक्स इससे बदल जाता है state.activethumb.checked = determineChecked().

determineChecked()

dragEnd के ज़रिए कॉल किया जाने वाला यह फ़ंक्शन, तय करता है कि अंगूठे करंट कहां है अपने ट्रैक की सीमाओं के अंदर होता है. साथ ही, अगर यह बराबर या इससे ज़्यादा हो, तो 'सही' दिखाता है ट्रैक के आधे हिस्से में:

const determineChecked = () => {
  let {bounds} = switches.get(state.activethumb.parentElement)

  let curpos =
    Math.abs(
      parseInt(
        state.activethumb.style.getPropertyValue('--thumb-position')))

  if (!curpos) {
    curpos = state.activethumb.checked
      ? bounds.lower
      : bounds.upper
  }

  return curpos >= bounds.middle
}

अतिरिक्त विचार

शुरुआती एचटीएमएल स्ट्रक्चर की वजह से, ड्रैग जेस्चर की वजह से कोड पर कुछ क्रेडिट लिमिट आ गई है चुना गया, खास तौर पर इनपुट को किसी लेबल में रैप करना. लेबल, अभिभावक होने के नाते एलिमेंट है, तो इनपुट के बाद क्लिक इंटरैक्शन मिलेंगे. आखिर में dragEnd इवेंट, शायद आपने padRelease() को अजीब तरीके से सुना हो फ़ंक्शन का इस्तेमाल करना होगा.

const padRelease = () => {
  state.recentlyDragged = true

  setTimeout(_ => {
    state.recentlyDragged = false
  }, 300)
}

यह उस लेबल को ध्यान में रखकर बनाया गया है जिस पर बाद में क्लिक किया जाएगा. इससे सही का निशान हट जाएगा, या देखें कि उपयोगकर्ता ने क्या इंटरैक्शन किया है.

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

मुझे इस तरह का JavaScript लिखना बहुत कम पसंद है, क्योंकि मुझे इसे मैनेज नहीं करना शर्तों के साथ इवेंट के लिए बबल्स की सुविधा:

const preventBubbles = event => {
  if (state.recentlyDragged)
    event.preventDefault() && event.stopPropagation()
}

नतीजा

इस बेहद छोटे हिस्से में स्विच करने से, जीयूआई चैलेंज पर सबसे ज़्यादा काम हुआ अभी तक! अब जब आपको पता है कि मैंने इसे कैसे किया, तो आप कैसे करेंगे ‽ 🙂

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

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

संसाधन

.gui-switch का सोर्स कोड यहां ढूंढें GitHub.