एक पेज के ऐप्लिकेशन के लिए, एक ही दस्तावेज़ वाले व्यू में ट्रांज़िशन

पब्लिश करने की तारीख: 17 अगस्त, 2021, पिछली बार अपडेट करने की तारीख: 25 सितंबर, 2024

जब व्यू ट्रांज़िशन किसी एक दस्तावेज़ पर चलता है, तो उसे एक ही दस्तावेज़ का व्यू ट्रांज़िशन कहा जाता है. आम तौर पर, ऐसा सिंगल-पेज ऐप्लिकेशन (एसपीए) में होता है, जहां डीओएम को अपडेट करने के लिए JavaScript का इस्तेमाल किया जाता है. Chrome 111 से, एक ही दस्तावेज़ के व्यू के बीच ट्रांज़िशन की सुविधा काम करती है.

एक ही दस्तावेज़ के व्यू ट्रांज़िशन को ट्रिगर करने के लिए, document.startViewTransition को कॉल करें:

function handleClick(e) {
  // Fallback for browsers that don't support this API:
  if (!document.startViewTransition) {
    updateTheDOMSomehow();
    return;
  }

  // With a View Transition:
  document.startViewTransition(() => updateTheDOMSomehow());
}

ट्रिगर होने पर, ब्राउज़र उन सभी एलिमेंट के स्नैपशॉट अपने-आप कैप्चर कर लेता है जिन पर view-transition-name सीएसएस प्रॉपर्टी का एलान किया गया है.

इसके बाद, यह DOM को अपडेट करने वाले पास किए गए कॉलबैक को लागू करता है. इसके बाद, यह नई स्थिति के स्नैपशॉट लेता है.

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


डिफ़ॉल्ट ट्रांज़िशन: क्रॉस-फ़ेड

डिफ़ॉल्ट व्यू ट्रांज़िशन, क्रॉस-फ़ेड होता है. इसलिए, यह एपीआई के बारे में अच्छी जानकारी देता है:

function spaNavigate(data) {
  // Fallback for browsers that don't support this API:
  if (!document.startViewTransition) {
    updateTheDOMSomehow(data);
    return;
  }

  // With a transition:
  document.startViewTransition(() => updateTheDOMSomehow(data));
}

जहां updateTheDOMSomehow, DOM को नई स्थिति में बदलता है. ऐसा करने के लिए, आपके पास कई विकल्प हैं. उदाहरण के लिए, एलिमेंट जोड़े या हटाए जा सकते हैं, क्लास के नाम बदले जा सकते हैं या स्टाइल बदली जा सकती हैं.

इस तरह, पेज क्रॉस-फ़ेड होते हैं:

डिफ़ॉल्ट क्रॉस-फ़ेड. कम से कम डेमो. सोर्स.

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


ये ट्रांज़िशन कैसे काम करते हैं

आइए, पिछले कोड सैंपल को अपडेट करते हैं.

document.startViewTransition(() => updateTheDOMSomehow(data));

.startViewTransition() को कॉल करने पर, एपीआई पेज की मौजूदा स्थिति कैप्चर करता है. इसमें स्क्रीनशॉट लेना भी शामिल है.

प्रोसेस पूरी होने के बाद, .startViewTransition() को पास किए गए कॉलबैक को कॉल किया जाता है. यहीं पर डीओएम बदला जाता है. इसके बाद, एपीआई पेज की नई स्थिति कैप्चर करता है.

नई स्थिति कैप्चर होने के बाद, एपीआई इस तरह का एक स्यूडो-एलिमेंट ट्री बनाता है:

::view-transition
└─ ::view-transition-group(root)
   └─ ::view-transition-image-pair(root)
      ├─ ::view-transition-old(root)
      └─ ::view-transition-new(root)

::view-transition, पेज पर मौजूद बाकी सभी चीज़ों के ऊपर, ओवरले में दिखता है. यह तब काम आता है, जब आपको ट्रांज़िशन के लिए बैकग्राउंड का रंग सेट करना हो.

::view-transition-old(root), पुराने व्यू का स्क्रीनशॉट है और ::view-transition-new(root), नए व्यू का लाइव वर्शन है. दोनों, सीएसएस 'बदले गए कॉन्टेंट' (जैसे कि <img>) के तौर पर रेंडर होते हैं.

पुराना व्यू, opacity: 1 से opacity: 0 पर ऐनिमेट होता है, जबकि नया व्यू opacity: 0 से opacity: 1 पर ऐनिमेट होता है. इससे क्रॉस-फ़ेड बनता है.

सभी ऐनिमेशन, सीएसएस ऐनिमेशन का इस्तेमाल करके दिखाए जाते हैं. इसलिए, उन्हें सीएसएस की मदद से पसंद के मुताबिक बनाया जा सकता है.

ट्रांज़िशन को पसंद के मुताबिक बनाना

व्यू ट्रांज़िशन के सभी स्यूडो-एलिमेंट को सीएसएस की मदद से टारगेट किया जा सकता है. साथ ही, ऐनिमेशन को सीएसएस का इस्तेमाल करके तय किया जाता है. इसलिए, मौजूदा सीएसएस ऐनिमेशन प्रॉपर्टी का इस्तेमाल करके, उनमें बदलाव किया जा सकता है. उदाहरण के लिए:

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 5s;
}

इस एक बदलाव से, फ़ेड अब बहुत धीमा हो गया है:

लंबा क्रॉस-फ़ेड. कम से कम डेमो. सोर्स.

ठीक है, अब भी यह शानदार नहीं है. इसके बजाय, नीचे दिया गया कोड Material Design के शेयर किए गए ऐक्सिस ट्रांज़िशन को लागू करता है:

@keyframes fade-in {
  from { opacity: 0; }
}

@keyframes fade-out {
  to { opacity: 0; }
}

@keyframes slide-from-right {
  from { transform: translateX(30px); }
}

@keyframes slide-to-left {
  to { transform: translateX(-30px); }
}

::view-transition-old(root) {
  animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}

::view-transition-new(root) {
  animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}

और नतीजा यह रहा:

शेयर किया गया ऐक्सिस ट्रांज़िशन. कम से कम डेमो. सोर्स.

एक से ज़्यादा एलिमेंट को ट्रांज़िशन करना

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

इससे बचने के लिए, हेडर को पेज के बाकी हिस्से से अलग किया जा सकता है, ताकि उसे अलग से ऐनिमेट किया जा सके. ऐसा करने के लिए, एलिमेंट को view-transition-name असाइन किया जाता है.

.main-header {
  view-transition-name: main-header;
}

view-transition-name की वैल्यू कुछ भी हो सकती है. हालांकि, none को वैल्यू के तौर पर नहीं इस्तेमाल किया जा सकता. इसका मतलब है कि ट्रांज़िशन का कोई नाम नहीं है. इसका इस्तेमाल, ट्रांज़िशन के दौरान एलिमेंट की यूनीक पहचान करने के लिए किया जाता है.

और इसका नतीजा:

फ़िक्स्ड हेडर के साथ शेयर किया गया ऐक्सिस ट्रांज़िशन. कम से कम डेमो. सोर्स.

अब हेडर अपनी जगह पर ही रहता है और क्रॉस-फ़ेड होता है.

सीएसएस एलान की वजह से, सूडो-एलिमेंट ट्री बदल गया:

::view-transition
├─ ::view-transition-group(root)
│  └─ ::view-transition-image-pair(root)
│     ├─ ::view-transition-old(root)
│     └─ ::view-transition-new(root)
└─ ::view-transition-group(main-header)
   └─ ::view-transition-image-pair(main-header)
      ├─ ::view-transition-old(main-header)
      └─ ::view-transition-new(main-header)

अब दो ट्रांज़िशन ग्रुप हैं. एक हेडर के लिए और दूसरा बाकी के लिए. इन्हें सीएसएस की मदद से अलग-अलग टारगेट किया जा सकता है और उन्हें अलग-अलग ट्रांज़िशन दिए जा सकते हैं. हालांकि, इस मामले में main-header को डिफ़ॉल्ट ट्रांज़िशन के साथ छोड़ दिया गया था, जो क्रॉस-फ़ेड है.

ठीक है, डिफ़ॉल्ट ट्रांज़िशन सिर्फ़ क्रॉस फ़ेड नहीं होता. ::view-transition-group भी ट्रांज़िशन करता है:

  • पोज़िशन और ट्रांसफ़ॉर्म (transform का इस्तेमाल करके)
  • चौड़ाई
  • ऊंचाई

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

.main-header-text {
  view-transition-name: main-header-text;
  width: fit-content;
}

fit-content का इस्तेमाल इसलिए किया जाता है, ताकि एलिमेंट, बाकी चौड़ाई तक स्ट्रेच होने के बजाय, टेक्स्ट के साइज़ का हो. इसके बिना, बैक ऐरो दोनों पेजों पर एक ही साइज़ के बजाय, हेडर टेक्स्ट एलिमेंट का साइज़ कम कर देता है.

इसलिए, अब हमारे पास तीन हिस्से हैं:

::view-transition
├─ ::view-transition-group(root)
│  └─ …
├─ ::view-transition-group(main-header)
│  └─ …
└─ ::view-transition-group(main-header-text)
   └─ …

हालांकि, फिर से डिफ़ॉल्ट सेटिंग का इस्तेमाल करें:

स्लाइडिंग हेडर टेक्स्ट. कम से कम डेमो. सोर्स.

अब हेडिंग का टेक्स्ट, बैक बटन के लिए जगह बनाने के लिए थोड़ा सा स्लाइड करता है.


view-transition-class का इस्तेमाल करके, एक ही तरह से कई स्यूडो-एलिमेंट को ऐनिमेट करना

ब्राउज़र के इस्तेमाल से जुड़ी सहायता

  • Chrome: 125.
  • किनारा: 125.
  • Firefox: यह सुविधा काम नहीं करती.
  • Safari Technology Preview: काम करता है.

मान लें कि आपके पास कार्ड के साथ-साथ पेज पर एक टाइटल वाला व्यू ट्रांज़िशन है. टाइटल को छोड़कर सभी कार्ड को ऐनिमेट करने के लिए, आपको एक ऐसा सिलेक्टर लिखना होगा जो हर कार्ड को टारगेट करता हो.

h1 {
    view-transition-name: title;
}
::view-transition-group(title) {
    animation-timing-function: ease-in-out;
}

#card1 { view-transition-name: card1; }
#card2 { view-transition-name: card2; }
#card3 { view-transition-name: card3; }
#card4 { view-transition-name: card4; }
…
#card20 { view-transition-name: card20; }

::view-transition-group(card1),
::view-transition-group(card2),
::view-transition-group(card3),
::view-transition-group(card4),
…
::view-transition-group(card20) {
    animation-timing-function: var(--bounce);
}

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

एक ही स्टाइल नियम लागू करने के लिए, view-transition-class का इस्तेमाल व्यू ट्रांज़िशन के स्यूडो-एलिमेंट में किया जा सकता है.

#card1 { view-transition-name: card1; }
#card2 { view-transition-name: card2; }
#card3 { view-transition-name: card3; }
#card4 { view-transition-name: card4; }
#card5 { view-transition-name: card5; }
…
#card20 { view-transition-name: card20; }

#cards-wrapper > div {
  view-transition-class: card;
}
html::view-transition-group(.card) {
  animation-timing-function: var(--bounce);
}

इस कार्ड के उदाहरण में, पिछले सीएसएस स्निपेट का इस्तेमाल किया गया है. सभी कार्ड, जिनमें नए कार्ड भी शामिल हैं, उन पर एक ही समय लागू होता है. इसके लिए, एक सिलेक्टर का इस्तेमाल किया जाता है: html::view-transition-group(.card).

कार्ड डेमो की रिकॉर्डिंग. view-transition-class का इस्तेमाल करके, जोड़े गए या हटाए गए कार्ड को छोड़कर, सभी कार्ड पर एक ही animation-timing-function लागू होता है.

ट्रांज़िशन डीबग करना

व्यू ट्रांज़िशन, सीएसएस ऐनिमेशन के ऊपर बनाए जाते हैं. इसलिए, Chrome DevTools में ऐनिमेशन पैनल, ट्रांज़िशन को डीबग करने के लिए बेहतरीन है.

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

Chrome DevTools की मदद से व्यू ट्रांज़िशन की गड़बड़ियों को डीबग करना.

ट्रांज़िशन करने वाले एलिमेंट, एक ही डीओएम एलिमेंट होने ज़रूरी नहीं हैं

अब तक, हमने हेडर और हेडर में मौजूद टेक्स्ट के लिए अलग-अलग ट्रांज़िशन एलिमेंट बनाने के लिए, view-transition-name का इस्तेमाल किया है. डीओएम में बदलाव होने से पहले और बाद में, ये कॉन्सेप्ट के हिसाब से एक ही एलिमेंट होते हैं. हालांकि, ऐसे ट्रांज़िशन भी बनाए जा सकते हैं जिनमें ऐसा नहीं होता.

उदाहरण के लिए, मुख्य वीडियो एम्बेड को view-transition-name दिया जा सकता है:

.full-embed {
  view-transition-name: full-embed;
}

इसके बाद, थंबनेल पर क्लिक करने पर, उसे सिर्फ़ ट्रांज़िशन के दौरान वही view-transition-name दिया जा सकता है:

thumbnail.onclick = async () => {
  thumbnail.style.viewTransitionName = 'full-embed';

  document.startViewTransition(() => {
    thumbnail.style.viewTransitionName = '';
    updateTheDOMSomehow();
  });
};

और नतीजा:

एक एलिमेंट से दूसरे एलिमेंट में ट्रांज़िशन करना. कम से कम डेमो. सोर्स.

इसके बाद, थंबनेल, मुख्य इमेज में बदल जाता है. हालांकि, ये कॉन्सेप्ट के हिसाब से (और असल में) अलग-अलग एलिमेंट हैं, लेकिन ट्रांज़िशन एपीआई उन्हें एक ही चीज़ मानता है, क्योंकि इनमें एक ही view-transition-name शेयर किया गया है.

इस ट्रांज़िशन का असल कोड, पिछले उदाहरण से थोड़ा ज़्यादा जटिल है, क्योंकि यह थंबनेल पेज पर वापस ट्रांज़िशन को भी मैनेज करता है. पूरी तरह से लागू करने के लिए, सोर्स देखें.


कस्टम एंट्री और एग्ज़िट ट्रांज़िशन

इस उदाहरण पर एक नज़र डालें:

साइडबार में जाना और उससे बाहर निकलना. कम से कम डेमो. सोर्स.

साइडबार, ट्रांज़िशन का हिस्सा है:

.sidebar {
  view-transition-name: sidebar;
}

हालांकि, पिछले उदाहरण में दिए गए हेडर के उलट, साइडबार सभी पेजों पर नहीं दिखता. अगर दोनों स्टेटस में साइडबार है, तो ट्रांज़िशन के स्यूडो-एलिमेंट इस तरह दिखते हैं:

::view-transition
├─ …other transition groups…
└─ ::view-transition-group(sidebar)
   └─ ::view-transition-image-pair(sidebar)
      ├─ ::view-transition-old(sidebar)
      └─ ::view-transition-new(sidebar)

हालांकि, अगर साइडबार सिर्फ़ नए पेज पर है, तो ::view-transition-old(sidebar) स्यूडो-एलिमेंट वहां नहीं होगा. साइडबार के लिए कोई 'पुरानी' इमेज नहीं है, इसलिए इमेज-पेयर में सिर्फ़ ::view-transition-new(sidebar) होगा. इसी तरह, अगर साइडबार सिर्फ़ पुराने पेज पर है, तो इमेज-पेयर में सिर्फ़ ::view-transition-old(sidebar) होगा.

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

एंट्री और एक्सिट ट्रांज़िशन बनाने के लिए, :only-child स्यूडो-क्लास का इस्तेमाल किया जा सकता है. इससे, पुराने या नए स्यूडो-एलिमेंट को टारगेट किया जा सकता है. ऐसा तब किया जा सकता है, जब इमेज-पेयर में सिर्फ़ एक चाइल्ड एलिमेंट हो:

/* Entry transition */
::view-transition-new(sidebar):only-child {
  animation: 300ms cubic-bezier(0, 0, 0.2, 1) both fade-in,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}

/* Exit transition */
::view-transition-old(sidebar):only-child {
  animation: 150ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-right;
}

इस मामले में, साइडबार दोनों स्थितियों में मौजूद होने पर कोई खास ट्रांज़िशन नहीं होता, क्योंकि डिफ़ॉल्ट ट्रांज़िशन सही होता है.

एक साथ काम नहीं करने वाले डीओएम अपडेट और कॉन्टेंट के लिए इंतज़ार करना

.startViewTransition() को पास किया गया कॉलबैक, एक प्रॉमिस दिखा सकता है. इससे डीओएम को अलग-अलग समय पर अपडेट किया जा सकता है. साथ ही, अहम कॉन्टेंट के तैयार होने का इंतज़ार किया जा सकता है.

document.startViewTransition(async () => {
  await something;
  await updateTheDOMSomehow();
  await somethingElse;
});

जब तक वादा पूरा नहीं हो जाता, तब तक ट्रांज़िशन शुरू नहीं होगा. इस दौरान, पेज फ़्रीज़ हो जाता है. इसलिए, इस प्रोसेस में लगने वाले समय को कम से कम रखा जाना चाहिए. खास तौर पर, .startViewTransition() कॉल करने से पहले, नेटवर्क फ़ेच किए जाने चाहिए, जबकि पेज पूरी तरह से इंटरैक्टिव हो. ऐसा .startViewTransition() कॉलबैक के हिस्से के तौर पर करने के बजाय किया जाना चाहिए.

अगर आपको इमेज या फ़ॉन्ट के लोड होने का इंतज़ार करना है, तो ज़्यादा से ज़्यादा टाइम आउट का इस्तेमाल करें:

const wait = ms => new Promise(r => setTimeout(r, ms));

document.startViewTransition(async () => {
  updateTheDOMSomehow();

  // Pause for up to 100ms for fonts to be ready:
  await Promise.race([document.fonts.ready, wait(100)]);
});

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


अपने मौजूदा कॉन्टेंट का ज़्यादा से ज़्यादा फ़ायदा पाना

अगर थंबनेल, बड़ी इमेज में ट्रांज़िशन करता है, तो:

थंबनेल, बड़ी इमेज में ट्रांज़िशन करता हुआ. डेमो साइट आज़माएं.

डिफ़ॉल्ट ट्रांज़िशन, क्रॉस-फ़ेड होता है. इसका मतलब है कि थंबनेल, अभी तक लोड नहीं हुई पूरी इमेज के साथ क्रॉस-फ़ेड हो सकता है.

इस समस्या को हल करने का एक तरीका यह है कि ट्रांज़िशन शुरू करने से पहले, पूरी इमेज लोड होने का इंतज़ार करें. आम तौर पर, यह काम .startViewTransition() को कॉल करने से पहले किया जाता है, ताकि पेज इंटरैक्टिव बना रहे. साथ ही, उपयोगकर्ता को यह बताने के लिए स्पिनर दिखाया जा सके कि चीज़ें लोड हो रही हैं. हालांकि, इस मामले में एक बेहतर तरीका है:

::view-transition-old(full-embed),
::view-transition-new(full-embed) {
  /* Prevent the default animation,
  so both views remain opacity:1 throughout the transition */
  animation: none;
  /* Use normal blending,
  so the new view sits on top and obscures the old view */
  mix-blend-mode: normal;
}

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

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

आसपेक्ट रेशियो में होने वाले बदलावों को हैंडल करना

फ़िलहाल, सभी ट्रांज़िशन एक ही आसपेक्ट रेशियो वाले एलिमेंट के लिए किए गए हैं. हालांकि, ऐसा हमेशा नहीं होगा. अगर थंबनेल 1:1 और मुख्य इमेज 16:9 है, तो क्या होगा?

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

डिफ़ॉल्ट ट्रांज़िशन में, ग्रुप पहले के साइज़ से लेकर बाद के साइज़ तक ऐनिमेट होता है. पुराने और नए व्यू, ग्रुप की 100% चौड़ाई और अपने-आप तय होने वाली ऊंचाई के होते हैं. इसका मतलब है कि ग्रुप के साइज़ के बावजूद, इनका आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) नहीं बदलता.

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

::view-transition-old(full-embed),
::view-transition-new(full-embed) {
  /* Prevent the default animation,
  so both views remain opacity:1 throughout the transition */
  animation: none;
  /* Use normal blending,
  so the new view sits on top and obscures the old view */
  mix-blend-mode: normal;
  /* Make the height the same as the group,
  meaning the view size might not match its aspect-ratio. */
  height: 100%;
  /* Clip any overflow of the view */
  overflow: clip;
}

/* The old view is the thumbnail */
::view-transition-old(full-embed) {
  /* Maintain the aspect ratio of the view,
  by shrinking it to fit within the bounds of the element */
  object-fit: contain;
}

/* The new view is the full image */
::view-transition-new(full-embed) {
  /* Maintain the aspect ratio of the view,
  by growing it to cover the bounds of the element */
  object-fit: cover;
}

इसका मतलब है कि चौड़ाई बढ़ने पर भी थंबनेल, एलिमेंट के बीच में ही रहता है. हालांकि, 1:1 से 16:9 में बदलने पर पूरी इमेज 'अन-क्रॉप' हो जाती है.

ज़्यादा जानकारी के लिए, व्यू ट्रांज़िशन: आसपेक्ट रेशियो में हुए बदलावों को मैनेज करना लेख पढ़ें


डिवाइस की अलग-अलग स्थितियों के लिए ट्रांज़िशन बदलने के लिए, मीडिया क्वेरी का इस्तेमाल करना

हो सकता है कि आप मोबाइल और डेस्कटॉप के लिए अलग-अलग ट्रांज़िशन का इस्तेमाल करना चाहें. जैसे, इस उदाहरण में मोबाइल पर साइड से पूरी स्लाइड की गई है, जबकि डेस्कटॉप पर ज़्यादा स्मूद स्लाइड की गई है:

एक एलिमेंट से दूसरे एलिमेंट में ट्रांज़िशन. कम से कम डेमो. सोर्स.

ऐसा करने के लिए, रेगुलर मीडिया क्वेरी का इस्तेमाल किया जा सकता है:

/* Transitions for mobile */
::view-transition-old(root) {
  animation: 300ms ease-out both full-slide-to-left;
}

::view-transition-new(root) {
  animation: 300ms ease-out both full-slide-from-right;
}

@media (min-width: 500px) {
  /* Overrides for larger displays.
  This is the shared axis transition from earlier in the article. */
  ::view-transition-old(root) {
    animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
      300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
  }

  ::view-transition-new(root) {
    animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
      300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
  }
}

आपके पास यह बदलने का विकल्प भी है कि मैच होने वाली मीडिया क्वेरी के आधार पर, किन एलिमेंट को view-transition-name असाइन किया जाए.


'कम मोशन' सेटिंग के लिए प्रतिक्रिया देना

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

आपके पास इन उपयोगकर्ताओं के लिए, ट्रांज़िशन को रोकने का विकल्प है:

@media (prefers-reduced-motion) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

हालांकि, 'कम मोशन' की सेटिंग चुनने का मतलब यह नहीं है कि उपयोगकर्ता कोई मोशन नहीं चाहता. ऊपर दिए गए स्निपेट के बजाय, कोई ऐसा ऐनिमेशन चुना जा सकता है जो ज़्यादा बेहतर नज़र न आए, लेकिन फिर भी एलिमेंट और डेटा के फ़्लो के बीच के संबंध को दिखाता हो.


व्यू ट्रांज़िशन टाइप की मदद से, व्यू ट्रांज़िशन के कई स्टाइल मैनेज करना

ब्राउज़र के इस्तेमाल से जुड़ी सहायता

  • Chrome: 125.
  • किनारा: 125.
  • Firefox: यह सुविधा काम नहीं करती.
  • Safari: 18.

कभी-कभी किसी एक व्यू से दूसरे व्यू पर जाने के लिए, खास तौर पर ट्रांज़िशन बनाया जाना चाहिए. उदाहरण के लिए, पेजेशन क्रम में अगले या पिछले पेज पर जाते समय, हो सकता है कि आप कॉन्टेंट को किसी दूसरी दिशा में स्लाइड करना चाहें. यह इस बात पर निर्भर करता है कि आपको क्रम में ऊपर वाले पेज पर जाना है या नीचे वाले पेज पर.

पेजेशन डेमो की रिकॉर्डिंग. यह इस बात पर निर्भर करता है कि आपको किस पेज पर जाना है.

इसके लिए, व्यू ट्रांज़िशन टाइप का इस्तेमाल किया जा सकता है. इससे, किसी चालू व्यू ट्रांज़िशन में एक या उससे ज़्यादा टाइप असाइन किए जा सकते हैं. उदाहरण के लिए, पेजेशन क्रम में किसी ऊपरी पेज पर ट्रांज़िशन करते समय, forwards टाइप का इस्तेमाल करें. वहीं, किसी निचले पेज पर जाने के लिए, backwards टाइप का इस्तेमाल करें. ये टाइप सिर्फ़ ट्रांज़िशन कैप्चर करने या करने के दौरान चालू होते हैं. अलग-अलग ऐनिमेशन का इस्तेमाल करने के लिए, हर टाइप को सीएसएस की मदद से पसंद के मुताबिक बनाया जा सकता है.

एक ही दस्तावेज़ के व्यू ट्रांज़िशन में टाइप का इस्तेमाल करने के लिए, startViewTransition तरीके में types पास करें. इसकी अनुमति देने के लिए, document.startViewTransition एक ऑब्जेक्ट भी स्वीकार करता है: update एक कॉलबैक फ़ंक्शन है, जो डीओएम को अपडेट करता है और types एक ऐरे है, जिसमें टाइप होते हैं.

const direction = determineBackwardsOrForwards();

const t = document.startViewTransition({
  update: updateTheDOMSomehow,
  types: ['slide', direction],
});
का इस्तेमाल करें

इन टाइप के सवालों के जवाब देने के लिए, :active-view-transition-type() सिलेक्टर का इस्तेमाल करें. सिलेक्टर में वह type डालें जिसे टारगेट करना है. इससे, एक-दूसरे के एलान में रुकावट डाले बिना, कई व्यू ट्रांज़िशन के स्टाइल को अलग-अलग रखा जा सकता है.

टाइप सिर्फ़ ट्रांज़िशन कैप्चर करने या करने पर लागू होते हैं. इसलिए, सिलेक्टर का इस्तेमाल करके किसी एलिमेंट पर view-transition-name को सिर्फ़ उस टाइप के व्यू ट्रांज़िशन के लिए सेट या अनसेट किया जा सकता है.

/* Determine what gets captured when the type is forwards or backwards */
html:active-view-transition-type(forwards, backwards) {
  :root {
    view-transition-name: none;
  }
  article {
    view-transition-name: content;
  }
  .pagination {
    view-transition-name: pagination;
  }
}

/* Animation styles for forwards type only */
html:active-view-transition-type(forwards) {
  &::view-transition-old(content) {
    animation-name: slide-out-to-left;
  }
  &::view-transition-new(content) {
    animation-name: slide-in-from-right;
  }
}

/* Animation styles for backwards type only */
html:active-view-transition-type(backwards) {
  &::view-transition-old(content) {
    animation-name: slide-out-to-right;
  }
  &::view-transition-new(content) {
    animation-name: slide-in-from-left;
  }
}

/* Animation styles for reload type only (using the default root snapshot) */
html:active-view-transition-type(reload) {
  &::view-transition-old(root) {
    animation-name: fade-out, scale-down;
  }
  &::view-transition-new(root) {
    animation-delay: 0.25s;
    animation-name: fade-in, scale-up;
  }
}

यहां दिए गए पेज पर नंबर डालने के डेमो में, पेज का कॉन्टेंट आगे या पीछे की ओर स्लाइड करता है. यह इस बात पर निर्भर करता है कि आपने पेज के किस नंबर पर नेविगेट किया है. क्लिक करने पर टाइप तय किए जाते हैं. इसके बाद, उन्हें document.startViewTransition में भेज दिया जाता है.

किसी भी टाइप के ऐक्टिव व्यू ट्रांज़िशन को टारगेट करने के लिए, :active-view-transition स्यूडो-क्लास सिलेक्टर का इस्तेमाल किया जा सकता है.

html:active-view-transition {
    …
}

व्यू ट्रांज़िशन रूट पर क्लास के नाम की मदद से, व्यू ट्रांज़िशन के कई स्टाइल मैनेज करना

कभी-कभी किसी खास तरह के व्यू से दूसरे व्यू पर जाने के लिए, खास तौर पर तैयार किया गया ट्रांज़िशन होना चाहिए. इसके अलावा, 'पीछे जाएं' नेविगेशन, 'आगे जाएं' नेविगेशन से अलग होना चाहिए.

'वापस जाएं' पर जाने पर अलग-अलग ट्रांज़िशन. कम से कम डेमो. सोर्स.

ट्रांज़िशन टाइप से पहले, इन मामलों को मैनेज करने का तरीका यह था कि ट्रांज़िशन रूट पर कुछ समय के लिए क्लास का नाम सेट किया जाता था. document.startViewTransition को कॉल करते समय, यह ट्रांज़िशन रूट <html> एलिमेंट होता है. इसे JavaScript में document.documentElement का इस्तेमाल करके ऐक्सेस किया जा सकता है:

if (isBackNavigation) {
  document.documentElement.classList.add('back-transition');
}

const transition = document.startViewTransition(() =>
  updateTheDOMSomehow(data)
);

try {
  await transition.finished;
} finally {
  document.documentElement.classList.remove('back-transition');
}

ट्रांज़िशन पूरा होने के बाद क्लास हटाने के लिए, इस उदाहरण में transition.finished का इस्तेमाल किया गया है. यह एक प्रॉमिस है, जो ट्रांज़िशन की आखिरी स्थिति तक पहुंचने के बाद रिज़ॉल्व होता है. इस ऑब्जेक्ट की अन्य प्रॉपर्टी के बारे में एपीआई रेफ़रंस में बताया गया है.

अब ट्रांज़िशन बदलने के लिए, अपनी सीएसएस में उस क्लास के नाम का इस्तेमाल किया जा सकता है:

/* 'Forward' transitions */
::view-transition-old(root) {
  animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}

::view-transition-new(root) {
  animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in, 300ms
      cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}

/* Overrides for 'back' transitions */
.back-transition::view-transition-old(root) {
  animation-name: fade-out, slide-to-right;
}

.back-transition::view-transition-new(root) {
  animation-name: fade-in, slide-from-left;
}

मीडिया क्वेरी की तरह, इन क्लास की मौजूदगी का इस्तेमाल यह तय करने के लिए भी किया जा सकता है कि किन एलिमेंट को view-transition-name मिलना चाहिए.


अन्य ऐनिमेशन को फ़्रीज़ किए बिना ट्रांज़िशन चलाना

वीडियो ट्रांज़िशन की पोज़िशन के इस डेमो को देखें:

वीडियो ट्रांज़िशन. कम से कम डेमो. सोर्स.

क्या आपको इसमें कोई गड़बड़ी दिखी? अगर ऐसा नहीं हुआ है, तो चिंता न करें. यहां इसे धीमा करके दिखाया गया है:

वीडियो ट्रांज़िशन, धीमा. कम से कम डेमो. सोर्स.

ट्रांज़िशन के दौरान, वीडियो फ़्रीज़ हो जाता है. इसके बाद, वीडियो का चलने वाला वर्शन फ़ेड इन हो जाता है. ऐसा इसलिए है, क्योंकि ::view-transition-old(video) पुराने व्यू का स्क्रीनशॉट है, जबकि ::view-transition-new(video) नए व्यू की लाइव इमेज है.

इसे ठीक किया जा सकता है. हालांकि, पहले खुद से पूछें कि क्या इसे ठीक करना ज़रूरी है. अगर ट्रांज़िशन सामान्य रफ़्तार से चलने पर आपको 'समस्या' नहीं दिखी, तो हम इसे बदलने की कोशिश नहीं करेंगे.

अगर आपको इसे ठीक करना है, तो ::view-transition-old(video) न दिखाएं. सीधे ::view-transition-new(video) पर स्विच करें. ऐसा करने के लिए, डिफ़ॉल्ट स्टाइल और ऐनिमेशन को बदलें:

::view-transition-old(video) {
  /* Don't show the frozen old view */
  display: none;
}

::view-transition-new(video) {
  /* Don't fade the new view in */
  animation: none;
}

यह बहुत आसान है!

वीडियो ट्रांज़िशन, धीमा. कम से कम डेमो. सोर्स.

अब वीडियो, ट्रांज़िशन के दौरान चलता रहेगा.


Navigation API (और अन्य फ़्रेमवर्क) के साथ इंटिग्रेशन

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

पेजेशन के इस डेमो से लिए गए नीचे दिए गए कोड स्निपेट में, नेविगेशन एपीआई के इंटरसेप्शन हैंडलर को अडजस्ट किया गया है, ताकि व्यू ट्रांज़िशन के काम करने पर document.startViewTransition को कॉल किया जा सके.

navigation.addEventListener("navigate", (e) => {
    // Don't intercept if not needed
    if (shouldNotIntercept(e)) return;

    // Intercept the navigation
    e.intercept({
        handler: async () => {
            // Fetch the new content
            const newContent = await fetchNewContent(e.destination.url, {
                signal: e.signal,
            });

            // The UA does not support View Transitions, or the UA
            // already provided a Visual Transition by itself (e.g. swipe back).
            // In either case, update the DOM directly
            if (!document.startViewTransition || e.hasUAVisualTransition) {
                setContent(newContent);
                return;
            }

            // Update the content using a View Transition
            const t = document.startViewTransition(() => {
                setContent(newContent);
            });
        }
    });
});

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

इसलिए, हमारा सुझाव है कि जब ब्राउज़र ने अपना विज़ुअल ट्रांज़िशन उपलब्ध कराया हो, तब व्यू ट्रांज़िशन शुरू होने से रोकें. ऐसा करने के लिए, NavigateEvent इंस्टेंस की hasUAVisualTransition प्रॉपर्टी की वैल्यू देखें. जब ब्राउज़र ने विज़ुअल ट्रांज़िशन दिया है, तो प्रॉपर्टी को true पर सेट किया जाता है. यह hasUIVisualTransition प्रॉपर्टी, PopStateEvent इंस्टेंस पर भी मौजूद होती है.

पिछले स्निपेट में, व्यू ट्रांज़िशन चलाने या न चलाने का फ़ैसला करने वाली जांच में, इस प्रॉपर्टी को ध्यान में रखा जाता है. जब एक ही दस्तावेज़ के व्यू ट्रांज़िशन के लिए कोई सहायता नहीं होती है या जब ब्राउज़र पहले से ही अपना ट्रांज़िशन उपलब्ध कराता है, तो व्यू ट्रांज़िशन को स्किप कर दिया जाता है.

if (!document.startViewTransition || e.hasUAVisualTransition) {
  setContent(newContent);
  return;
}

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

hasUAVisualTransition की जांच के बिना (बाईं ओर) और चौड़ाई (दाईं ओर) वाली एक ही साइट की तुलना
के साथ काम करती है.

JavaScript की मदद से ऐनिमेशन बनाना

अब तक, सभी ट्रांज़िशन को सीएसएस का इस्तेमाल करके तय किया गया है. हालांकि, कभी-कभी सीएसएस का इस्तेमाल करना काफ़ी नहीं होता:

सर्कल ट्रांज़िशन. कम से कम डेमो. सोर्स.

इस ट्रांज़िशन के कुछ हिस्सों को सिर्फ़ सीएसएस की मदद से पूरा नहीं किया जा सकता:

  • ऐनिमेशन, क्लिक की गई जगह से शुरू होता है.
  • ऐनिमेशन, सबसे दूर के कोने तक त्रिज्या वाले सर्कल पर खत्म होता है. हालांकि, हमें उम्मीद है कि आने वाले समय में सीएसएस की मदद से ऐसा किया जा सकेगा.

हालांकि, Web Animation API का इस्तेमाल करके ट्रांज़िशन बनाए जा सकते हैं!

let lastClick;
addEventListener('click', event => (lastClick = event));

function spaNavigate(data) {
  // Fallback for browsers that don't support this API:
  if (!document.startViewTransition) {
    updateTheDOMSomehow(data);
    return;
  }

  // Get the click position, or fallback to the middle of the screen
  const x = lastClick?.clientX ?? innerWidth / 2;
  const y = lastClick?.clientY ?? innerHeight / 2;
  // Get the distance to the furthest corner
  const endRadius = Math.hypot(
    Math.max(x, innerWidth - x),
    Math.max(y, innerHeight - y)
  );

  // With a transition:
  const transition = document.startViewTransition(() => {
    updateTheDOMSomehow(data);
  });

  // Wait for the pseudo-elements to be created:
  transition.ready.then(() => {
    // Animate the root's new view
    document.documentElement.animate(
      {
        clipPath: [
          `circle(0 at ${x}px ${y}px)`,
          `circle(${endRadius}px at ${x}px ${y}px)`,
        ],
      },
      {
        duration: 500,
        easing: 'ease-in',
        // Specify which pseudo-element to animate
        pseudoElement: '::view-transition-new(root)',
      }
    );
  });
}

इस उदाहरण में transition.ready का इस्तेमाल किया गया है. यह एक प्रॉमिस है, जो ट्रांज़िशन के स्यूडो-एलिमेंट बन जाने के बाद रिज़ॉल्व हो जाता है. इस ऑब्जेक्ट की अन्य प्रॉपर्टी के बारे में एपीआई रेफ़रंस में बताया गया है.


बेहतर बनाने के लिए ट्रांज़िशन

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

ट्रांज़िशन को बेहतर बनाने के लिए, ट्रांज़िशन प्रॉमिस का इस्तेमाल इस तरह से न करें कि ट्रांज़िशन पूरा न होने पर आपका ऐप्लिकेशन क्रैश हो जाए.

यह न करें
async function switchView(data) {
  // Fallback for browsers that don't support this API:
  if (!document.startViewTransition) {
    await updateTheDOM(data);
    return;
  }

  const transition = document.startViewTransition(async () => {
    await updateTheDOM(data);
  });

  await transition.ready;

  document.documentElement.animate(
    {
      clipPath: [`inset(50%)`, `inset(0)`],
    },
    {
      duration: 500,
      easing: 'ease-in',
      pseudoElement: '::view-transition-new(root)',
    }
  );
}

इस उदाहरण में समस्या यह है कि अगर ट्रांज़िशन ready स्टेटस तक नहीं पहुंच पाता है, तो switchView() अस्वीकार कर दिया जाएगा. हालांकि, इसका मतलब यह नहीं है कि व्यू स्विच नहीं हो पाया. हो सकता है कि डीओएम अपडेट हो गया हो, लेकिन डुप्लीकेट view-transition-name मौजूद थे. इसलिए, ट्रांज़िशन को छोड़ दिया गया.

इसके बजाय:

यह करें
async function switchView(data) {
  // Fallback for browsers that don't support this API:
  if (!document.startViewTransition) {
    await updateTheDOM(data);
    return;
  }

  const transition = document.startViewTransition(async () => {
    await updateTheDOM(data);
  });

  animateFromMiddle(transition);

  await transition.updateCallbackDone;
}

async function animateFromMiddle(transition) {
  try {
    await transition.ready;

    document.documentElement.animate(
      {
        clipPath: [`inset(50%)`, `inset(0)`],
      },
      {
        duration: 500,
        easing: 'ease-in',
        pseudoElement: '::view-transition-new(root)',
      }
    );
  } catch (err) {
    // You might want to log this error, but it shouldn't break the app
  }
}

इस उदाहरण में, डीओएम अपडेट होने का इंतज़ार करने और अपडेट न होने पर उसे अस्वीकार करने के लिए, transition.updateCallbackDone का इस्तेमाल किया गया है. ट्रांज़िशन पूरा न होने पर, switchView अब अस्वीकार नहीं करता. डीओएम अपडेट पूरा होने पर, यह ट्रांज़िशन पूरा हो जाता है और अपडेट पूरा न होने पर, इसे अस्वीकार कर दिया जाता है.

अगर आपको switchView को तब रिज़ॉल्व करना है, जब नया व्यू 'सेटल' हो गया हो, जैसे कि ऐनिमेशन वाला कोई ट्रांज़िशन पूरा हो गया हो या उसे स्किप करके आखिर तक पहुंचा गया हो, तो transition.updateCallbackDone को transition.finished से बदलें.


यह कोई पॉलीफ़िल नहीं है, लेकिन…

इस सुविधा को पॉलीफ़िल करना आसान नहीं है. हालांकि, यह हेल्पर फ़ंक्शन उन ब्राउज़र में चीज़ों को ज़्यादा आसान बनाता है जिनमें व्यू ट्रांज़िशन की सुविधा काम नहीं करती:

function transitionHelper({
  skipTransition = false,
  types = [],
  update,
}) {

  const unsupported = (error) => {
    const updateCallbackDone = Promise.resolve(update()).then(() => {});

    return {
      ready: Promise.reject(Error(error)),
      updateCallbackDone,
      finished: updateCallbackDone,
      skipTransition: () => {},
      types,
    };
  }

  if (skipTransition || !document.startViewTransition) {
    return unsupported('View Transitions are not supported in this browser');
  }

  try {
    const transition = document.startViewTransition({
      update,
      types,
    });

    return transition;
  } catch (e) {
    return unsupported('View Transitions with types are not supported in this browser');
  }
}

इसका इस्तेमाल इस तरह किया जा सकता है:

function spaNavigate(data) {
  const types = isBackNavigation ? ['back-transition'] : [];

  const transition = transitionHelper({
    update() {
      updateTheDOMSomehow(data);
    },
    types,
  });

  // …
}

जिन ब्राउज़र पर व्यू ट्रांज़िशन की सुविधा काम नहीं करती उनमें updateDOM को अब भी कॉल किया जाएगा. हालांकि, इसमें ऐनिमेशन वाला ट्रांज़िशन नहीं होगा.

ट्रांज़िशन के दौरान, <html> में जोड़ने के लिए कुछ classNames भी दिए जा सकते हैं. इससे नेविगेशन के टाइप के हिसाब से ट्रांज़िशन को आसानी से बदला जा सकता है.

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


फ़्रेमवर्क के साथ काम करना

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

  • React—यहां मुख्य बात flushSync है, जो स्टेटस में हुए बदलावों के सेट को सिंक करके लागू करता है. हां, उस एपीआई का इस्तेमाल करने के बारे में एक बड़ी चेतावनी दी गई है. हालांकि, डैन अब्रामोव ने मुझे भरोसा दिलाया है कि इस मामले में यह सही है. React और असाइन किए गए कोड की तरह ही, startViewTransition से मिले अलग-अलग प्रॉमिस का इस्तेमाल करते समय, ध्यान रखें कि आपका कोड सही स्थिति में चल रहा हो.
  • Vue.js—यहां nextTick कुंजी है, जो DOM अपडेट होने के बाद पूरा होता है.
  • Svelte—यह Vue से काफ़ी मिलता-जुलता है. हालांकि, अगले बदलाव का इंतज़ार करने का तरीका tick है.
  • Lit—यहां कॉम्पोनेंट में मौजूद this.updateComplete प्रॉमिस अहम है. यह डीओएम अपडेट होने के बाद पूरा होता है.
  • Angular—यहां applicationRef.tick कुंजी है, जो DOM में किए गए बदलावों को फ़्लश करता है. Angular के वर्शन 17 से, @angular/router के साथ आने वाले withViewTransitions का इस्तेमाल किया जा सकता है.

एपीआई का संदर्भ

const viewTransition = document.startViewTransition(update)

नया ViewTransition शुरू करें.

update एक ऐसा फ़ंक्शन है जिसे दस्तावेज़ की मौजूदा स्थिति कैप्चर होने के बाद कॉल किया जाता है.

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

const viewTransition = document.startViewTransition({ update, types })

तय किए गए टाइप के साथ नया ViewTransition शुरू करना

दस्तावेज़ की मौजूदा स्थिति कैप्चर होने के बाद, update को कॉल किया जाता है.

types, ट्रांज़िशन कैप्चर करते या करते समय, ट्रांज़िशन के लिए ऐक्टिव टाइप सेट करता है. यह शुरुआत में खाली होता है. ज़्यादा जानकारी के लिए, नीचे viewTransition.types देखें.

ViewTransition के इंस्टेंस के सदस्य:

viewTransition.updateCallbackDone

ऐसा प्रॉमिस जो updateCallback से मिलने वाले प्रॉमिस के पूरा होने पर पूरा होता है या अस्वीकार होने पर अस्वीकार होता है.

View Transition API, DOM में किए गए बदलाव को रैप करता है और ट्रांज़िशन बनाता है. हालांकि, कभी-कभी आपको ट्रांज़िशन ऐनिमेशन के काम करने या न करने की परवाह नहीं होती. आपको सिर्फ़ यह जानना होता है कि डीओएम में बदलाव हुआ है या नहीं और कब हुआ. updateCallbackDone उस इस्तेमाल के उदाहरण के लिए है.

viewTransition.ready

यह एक ऐसा वादा है जो ट्रांज़िशन के लिए सूडो-एलिमेंट बनने और ऐनिमेशन शुरू होने के बाद पूरा होता है.

अगर ट्रांज़िशन शुरू नहीं हो पाता है, तो यह अस्वीकार कर दिया जाता है. ऐसा गलत कॉन्फ़िगरेशन की वजह से हो सकता है. जैसे, डुप्लीकेट view-transition-name या updateCallback से अस्वीकार किया गया प्रॉमिस मिलना.

यह JavaScript की मदद से ट्रांज़िशन के स्यूडो-एलिमेंट को ऐनिमेट करने के लिए काम का है.

viewTransition.finished

यह एक ऐसा प्रॉमिस है जो तब पूरा होता है, जब उपयोगकर्ता को आखिरी स्टेटस पूरी तरह से दिखता है और वह उससे इंटरैक्ट कर सकता है.

यह सिर्फ़ तब अस्वीकार होता है, जब updateCallback अस्वीकार किया गया प्रॉमिस दिखाता है. इससे पता चलता है कि आखिरी स्थिति नहीं बनाई गई थी.

अगर ट्रांज़िशन शुरू नहीं होता है या ट्रांज़िशन के दौरान उसे छोड़ दिया जाता है, तब भी आखिरी स्टेटस पर पहुंचा जा सकता है. इसलिए, finished पूरा हो जाता है.

viewTransition.types

Set जैसा ऑब्जेक्ट, जिसमें ऐक्टिव व्यू ट्रांज़िशन के टाइप होते हैं. एंट्री में बदलाव करने के लिए, इसके इंस्टेंस के तरीके clear(), add(), और delete() का इस्तेमाल करें.

सीएसएस में किसी खास टाइप का जवाब देने के लिए, ट्रांज़िशन रूट पर :active-view-transition-type(type) स्यूडो-क्लास सिलेक्टर का इस्तेमाल करें.

व्यू ट्रांज़िशन पूरा होने पर, टाइप अपने-आप हट जाते हैं.

viewTransition.skipTransition()

ट्रांज़िशन के ऐनिमेशन वाले हिस्से को स्किप करें.

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


डिफ़ॉल्ट स्टाइल और ट्रांज़िशन का रेफ़रंस

::view-transition
व्यूपोर्ट को भरने वाला रूट स्यूडो-एलिमेंट, जिसमें हर ::view-transition-group शामिल होता है.
::view-transition-group

बिल्कुल सही जगह पर है.

'पहले' और 'बाद' स्टेटस के बीच ट्रांज़िशन width और height.

व्यूपोर्ट-स्पेस क्वॉड के 'पहले' और 'बाद' के बीच ट्रांज़िशन transform.

::view-transition-image-pair

ग्रुप को भरने के लिए पूरी तरह से सही जगह पर है.

पुराने और नए व्यू पर mix-blend-mode के असर को सीमित करने के लिए, isolation: isolate का इस्तेमाल किया जा सकता है.

::view-transition-new और ::view-transition-old

रैपर के सबसे ऊपर बाईं ओर पूरी तरह से पोज़िशन किया गया.

यह ग्रुप की चौड़ाई को 100% तक भर देता है. हालांकि, इसकी ऊंचाई अपने-आप सेट होती है. इसलिए, यह ग्रुप को भरने के बजाय, अपना आसपेक्ट रेशियो बनाए रखेगा.

mix-blend-mode: plus-lighter को सही क्रॉस-फ़ेड की अनुमति दी गई हो.

पुराना व्यू, opacity: 1 से opacity: 0 में बदल जाता है. नया व्यू, opacity: 0 से opacity: 1 पर ट्रांज़िशन करता है.


सुझाव/राय दें या शिकायत करें

डेवलपर के सुझाव, शिकायत या राय का हमेशा स्वागत है. ऐसा करने के लिए, GitHub पर सीएसएस वर्किंग ग्रुप के साथ समस्या दर्ज करें. इसमें सुझाव और सवाल शामिल करें. अपनी समस्या के आगे [css-view-transitions] जोड़ें.

अगर आपको कोई गड़बड़ी मिलती है, तो Chromium में गड़बड़ी की शिकायत करें.