একক-পৃষ্ঠার অ্যাপ্লিকেশনের জন্য একই-নথি দৃশ্য রূপান্তর

প্রকাশিত: ১৭ আগস্ট, ২০২১, সর্বশেষ আপডেট: ২৫ সেপ্টেম্বর, ২০২৪

যখন একটি একক ডকুমেন্টে একটি ভিউ ট্রানজিশন চলে তখন তাকে একই-ডকুমেন্ট ভিউ ট্রানজিশন বলা হয়। এটি সাধারণত একক-পৃষ্ঠা অ্যাপ্লিকেশন (SPA) এর ক্ষেত্রে হয় যেখানে DOM আপডেট করার জন্য জাভাস্ক্রিপ্ট ব্যবহার করা হয়। Chrome 111 এর মতো Chrome-এ একই-ডকুমেন্ট ভিউ ট্রানজিশন সমর্থিত।

একই-ডকুমেন্ট ভিউ ট্রানজিশন ট্রিগার করতে, 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 CSS প্রোপার্টি ঘোষিত থাকে।

এরপর এটি পাস করা কলব্যাকটি কার্যকর করে যা DOM আপডেট করে, যার পরে এটি নতুন অবস্থার স্ন্যাপশট নেয়।

এই স্ন্যাপশটগুলি তারপর ছদ্ম-উপাদানের একটি বৃক্ষে সাজানো হয় এবং CSS অ্যানিমেশনের শক্তি ব্যবহার করে অ্যানিমেটেড করা হয়। পুরাতন এবং নতুন অবস্থা থেকে জোড়া স্ন্যাপশটগুলি তাদের পুরানো অবস্থান এবং আকার থেকে তাদের নতুন অবস্থানে মসৃণভাবে স্থানান্তরিত হয়, যখন তাদের বিষয়বস্তু ক্রসফেইড হয়। আপনি যদি চান, আপনি অ্যানিমেশনগুলি কাস্টমাইজ করতে CSS ব্যবহার করতে পারেন।


ডিফল্ট রূপান্তর: ক্রস-ফেইড

ডিফল্ট ভিউ ট্রানজিশনটি ক্রস-ফেড, তাই এটি API-এর একটি চমৎকার ভূমিকা হিসেবে কাজ করে:

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() কল করা হয়, তখন API পৃষ্ঠার বর্তমান অবস্থা ক্যাপচার করে। এর মধ্যে একটি স্ন্যাপশট নেওয়াও অন্তর্ভুক্ত।

একবার সম্পূর্ণ হয়ে গেলে, .startViewTransition() এ পাস করা কলব্যাকটি কল করা হয়। সেখানেই DOM পরিবর্তন করা হয়। তারপর, API পৃষ্ঠার নতুন অবস্থা ক্যাপচার করে।

নতুন অবস্থাটি ক্যাপচার করার পরে, API এইভাবে একটি ছদ্ম-উপাদান ট্রি তৈরি করে:

::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) হল নতুন ভিউয়ের একটি লাইভ উপস্থাপনা। উভয়ই CSS 'প্রতিস্থাপিত কন্টেন্ট' হিসাবে রেন্ডার করে (যেমন <img> )।

পুরাতন ভিউটি opacity: 1 থেকে opacity: 0 তে অ্যানিমেট করে, যেখানে নতুন ভিউটি opacity: 0 থেকে opacity: 1 তে অ্যানিমেট করে, একটি ক্রস-ফেড তৈরি করে।

সমস্ত অ্যানিমেশন CSS অ্যানিমেশন ব্যবহার করে করা হয়, তাই সেগুলিকে CSS দিয়ে কাস্টমাইজ করা যায়।

ট্রানজিশনটি কাস্টমাইজ করুন

সমস্ত ভিউ ট্রানজিশন সিউডো-এলিমেন্ট CSS দিয়ে লক্ষ্য করা যেতে পারে, এবং যেহেতু অ্যানিমেশনগুলি CSS ব্যবহার করে সংজ্ঞায়িত করা হয়, তাই আপনি বিদ্যমান CSS অ্যানিমেশন বৈশিষ্ট্য ব্যবহার করে সেগুলি পরিবর্তন করতে পারেন। উদাহরণস্বরূপ:

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

সেই একটি পরিবর্তনের সাথে, বিবর্ণতা এখন সত্যিই ধীর:

লম্বা ক্রস-ফেড। ন্যূনতম ডেমোউৎস

ঠিক আছে, এটা এখনও চিত্তাকর্ষক নয়। পরিবর্তে, নিম্নলিখিত কোডটি ম্যাটেরিয়াল ডিজাইনের শেয়ার্ড অক্ষ রূপান্তর বাস্তবায়ন করে:

@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 ব্যতীত, যার অর্থ কোনও রূপান্তর নাম নেই)। এটি রূপান্তর জুড়ে উপাদানটিকে অনন্যভাবে সনাক্ত করতে ব্যবহৃত হয়।

এবং এর ফলাফল:

স্থির হেডার সহ ভাগ করা অক্ষের রূপান্তর। ন্যূনতম ডেমোউৎস

এখন হেডারটি যথাস্থানে থাকে এবং ক্রস-ফেইড হয়ে যায়।

সেই CSS ঘোষণার ফলে ছদ্ম-উপাদান ট্রি পরিবর্তন হয়েছিল:

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

এখন দুটি ট্রানজিশন গ্রুপ আছে। একটি হেডারের জন্য, এবং অন্যটি বাকিদের জন্য। CSS এর মাধ্যমে এগুলিকে স্বাধীনভাবে লক্ষ্য করা যেতে পারে এবং বিভিন্ন ট্রানজিশন দেওয়া যেতে পারে। যদিও, এই ক্ষেত্রে main-header ডিফল্ট ট্রানজিশনের সাথেই রয়ে গেছে, যা একটি ক্রস-ফেইড।

আচ্ছা, ঠিক আছে, ডিফল্ট ট্রানজিশনটি কেবল একটি ক্রস ফেইড নয়, ::view-transition-group এছাড়াও ট্রানজিশন করে:

  • অবস্থান এবং রূপান্তর (একটি transform ব্যবহার করে)
  • প্রস্থ
  • উচ্চতা

এখন পর্যন্ত এটা কোন ব্যাপার না, কারণ DOM পরিবর্তনের উভয় পাশে হেডারের আকার এবং অবস্থান একই। তবে আপনি হেডারের লেখাটিও বের করতে পারেন:

.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 ব্যবহার করে একইভাবে একাধিক ছদ্ম-উপাদান অ্যানিমেট করুন

Browser Support

  • ক্রোম: ১২৫।
  • প্রান্ত: ১২৫।
  • ফায়ারফক্স: ১৪৪।
  • সাফারি: ১৮.২।

Source

ধরুন আপনার কাছে একগুচ্ছ কার্ডের ভিউ ট্রানজিশন আছে, কিন্তু পৃষ্ঠায় একটি শিরোনামও আছে। শিরোনাম ছাড়া বাকি সব কার্ড অ্যানিমেট করার জন্য, আপনাকে একটি নির্বাচক লিখতে হবে যা প্রতিটি কার্ডকে লক্ষ্য করে।

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

২০টি এলিমেন্ট আছে? তাহলে ২০টি সিলেক্টর লিখতে হবে। নতুন এলিমেন্ট যোগ করতে চান? তাহলে অ্যানিমেশন স্টাইল প্রয়োগকারী সিলেক্টরও বাড়াতে হবে। ঠিক স্কেলেবল নয়।

একই স্টাইল নিয়ম প্রয়োগ করার জন্য ভিউ ট্রানজিশন সিউডো-এলিমেন্টগুলিতে 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);
}

নিচের কার্ডের উদাহরণটি পূর্ববর্তী CSS স্নিপেট ব্যবহার করে। নতুন যোগ করা কার্ডগুলি সহ সমস্ত কার্ডের জন্য একই সময়কাল একটি নির্বাচকের সাথে প্রয়োগ করা হয়: html::view-transition-group(.card)

কার্ডস ডেমো রেকর্ডিং। view-transition-class ব্যবহার করে এটি যোগ করা বা সরানো কার্ডগুলি ছাড়া সকল কার্ডে একই animation-timing-function প্রয়োগ করে।

ডিবাগ ট্রানজিশন

যেহেতু ভিউ ট্রানজিশনগুলি CSS অ্যানিমেশনের উপরে তৈরি করা হয়, তাই Chrome DevTools-এর অ্যানিমেশন প্যানেলটি ট্রানজিশন ডিবাগ করার জন্য দুর্দান্ত।

অ্যানিমেশন প্যানেল ব্যবহার করে, আপনি পরবর্তী অ্যানিমেশনটি থামাতে পারেন, তারপর অ্যানিমেশনটি এদিক-ওদিক স্ক্রাব করতে পারেন। এই সময়, এলিমেন্টস প্যানেলে ট্রানজিশন সিউডো-এলিমেন্টগুলি পাওয়া যাবে।

Chrome DevTools ব্যবহার করে ভিউ ট্রানজিশন ডিবাগ করা হচ্ছে।

ট্রানজিশনিং এলিমেন্টগুলিকে একই DOM এলিমেন্ট হতে হবে না।

এখন পর্যন্ত আমরা হেডার এবং হেডারের টেক্সটের জন্য আলাদা ট্রানজিশন এলিমেন্ট তৈরি করতে view-transition-name ব্যবহার করেছি। DOM পরিবর্তনের আগে এবং পরে ধারণাগতভাবে এগুলি একই উপাদান, তবে যেখানে এটি হয় না সেখানে আপনি ট্রানজিশন তৈরি করতে পারেন।

উদাহরণস্বরূপ, প্রধান ভিডিও এম্বেডকে একটি 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();
  });
};

এবং ফলাফল:

একটি উপাদান অন্যটিতে রূপান্তরিত হচ্ছে। ন্যূনতম ডেমোউৎস

থাম্বনেইলটি এখন মূল ছবিতে রূপান্তরিত হয়। যদিও ধারণাগতভাবে (এবং আক্ষরিক অর্থে) এগুলি ভিন্ন উপাদান, ট্রানজিশন API এগুলিকে একই জিনিস হিসাবে বিবেচনা করে কারণ তারা একই 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) ছদ্ম-উপাদানটি সেখানে থাকবে না। যেহেতু সাইডবারের জন্য কোনও 'পুরাতন' চিত্র নেই, তাই image-pair-এ কেবল একটি ::view-transition-new(sidebar) থাকবে। একইভাবে, যদি সাইডবারটি শুধুমাত্র পুরানো পৃষ্ঠায় থাকে, তাহলে image-pair-এ কেবল একটি ::view-transition-old(sidebar) থাকবে।

পূর্ববর্তী ডেমোতে, সাইডবারটি উভয় অবস্থায় প্রবেশ করছে, প্রস্থান করছে, নাকি উপস্থিত, তার উপর নির্ভর করে ভিন্নভাবে রূপান্তরিত হয়। এটি ডান দিক থেকে স্লাইড করে এবং ফেইড ইন করে প্রবেশ করে, এটি ডান দিকে স্লাইড করে এবং ফেইড আউট করে প্রস্থান করে এবং উভয় অবস্থায় উপস্থিত থাকলে এটি স্থানে থাকে।

নির্দিষ্ট এন্ট্রি এবং এক্সিট ট্রানজিশন তৈরি করতে, আপনি :only-child pseudo-class ব্যবহার করে পুরানো বা নতুন pseudo-elements টার্গেট করতে পারেন যখন এটি ইমেজ-পেয়ারের একমাত্র শিশু হয়:

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

এই ক্ষেত্রে, সাইডবার উভয় অবস্থায় উপস্থিত থাকলে কোন নির্দিষ্ট পরিবর্তন নেই, কারণ ডিফল্টটি নিখুঁত।

অ্যাসিঙ্ক DOM আপডেট এবং কন্টেন্টের জন্য অপেক্ষা করা হচ্ছে

.startViewTransition() এ পাস করা কলব্যাক একটি প্রতিশ্রুতি ফেরত দিতে পারে, যা অ্যাসিঙ্ক DOM আপডেটের জন্য অনুমতি দেয় এবং গুরুত্বপূর্ণ কন্টেন্ট প্রস্তুত হওয়ার জন্য অপেক্ষা করে।

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 দেবেন তাও পরিবর্তন করতে পারেন, যা মিডিয়া কোয়েরির সাথে মিলে যায় তার উপর নির্ভর করে।


'হ্রাসকৃত গতি' পছন্দের প্রতি প্রতিক্রিয়া জানান

ব্যবহারকারীরা তাদের অপারেটিং সিস্টেমের মাধ্যমে ইঙ্গিত দিতে পারেন যে তারা কম গতি পছন্দ করেন এবং সেই পছন্দটি CSS-এ প্রকাশিত হয়।

আপনি এই ব্যবহারকারীদের জন্য যেকোনো পরিবর্তন রোধ করতে পারেন:

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

তবে, 'হ্রাসকৃত গতি' পছন্দ করার অর্থ এই নয় যে ব্যবহারকারী কোনও গতি চান না। পূর্ববর্তী স্নিপেটের পরিবর্তে, আপনি আরও সূক্ষ্ম অ্যানিমেশন বেছে নিতে পারেন, তবে এমন একটি যা উপাদানগুলির মধ্যে সম্পর্ক এবং ডেটা প্রবাহকে প্রকাশ করে।


ভিউ ট্রানজিশন টাইপ সহ একাধিক ভিউ ট্রানজিশন স্টাইল পরিচালনা করুন

Browser Support

  • ক্রোম: ১২৫।
  • প্রান্ত: ১২৫।
  • ফায়ারফক্স: ১৪৪।
  • সাফারি: ১৮টি।

Source

কখনও কখনও একটি নির্দিষ্ট ভিউ থেকে অন্য ভিউতে রূপান্তরের জন্য একটি বিশেষভাবে তৈরি রূপান্তর থাকা উচিত। উদাহরণস্বরূপ, পৃষ্ঠাকরণ ক্রম অনুসারে পরবর্তী বা পূর্ববর্তী পৃষ্ঠায় যাওয়ার সময়, আপনি ক্রম থেকে উপরের পৃষ্ঠায় যাচ্ছেন নাকি নীচের পৃষ্ঠায় যাচ্ছেন তার উপর নির্ভর করে আপনি বিষয়বস্তুগুলিকে ভিন্ন দিকে স্লাইড করতে চাইতে পারেন।

পেজিনেশন ডেমোর রেকর্ডিং। আপনি কোন পৃষ্ঠায় যাচ্ছেন তার উপর নির্ভর করে এটি বিভিন্ন ট্রানজিশন ব্যবহার করে।

এর জন্য আপনি ভিউ ট্রানজিশন টাইপ ব্যবহার করতে পারেন, যা আপনাকে একটি সক্রিয় ভিউ ট্রানজিশনে এক বা একাধিক টাইপ বরাদ্দ করতে দেয়। উদাহরণস্বরূপ, পেজিনেশন সিকোয়েন্সে উচ্চতর পৃষ্ঠায় যাওয়ার সময় forwards টাইপ ব্যবহার করুন এবং নীচের পৃষ্ঠায় যাওয়ার সময় backwards টাইপ ব্যবহার করুন। এই টাইপগুলি কেবল একটি ট্রানজিশন ক্যাপচার বা সম্পাদন করার সময় সক্রিয় থাকে এবং প্রতিটি টাইপকে বিভিন্ন অ্যানিমেশন ব্যবহার করার জন্য CSS এর মাধ্যমে কাস্টমাইজ করা যেতে পারে।

একই-ডকুমেন্ট ভিউ ট্রানজিশনে টাইপ ব্যবহার করার জন্য, আপনাকে types startViewTransition পদ্ধতিতে পাস করতে হবে। এটি করার জন্য, document.startViewTransition একটি অবজেক্টও গ্রহণ করে: update হল কলব্যাক ফাংশন যা DOM আপডেট করে, এবং 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> এলিমেন্ট, যা জাভাস্ক্রিপ্টে 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 ব্যবহার করা হয়েছে, একটি প্রতিশ্রুতি যা ট্রানজিশন শেষ অবস্থায় পৌঁছানোর পরে সমাধান হয়ে যায়। এই অবজেক্টের অন্যান্য বৈশিষ্ট্যগুলি API রেফারেন্সে অন্তর্ভুক্ত করা হয়েছে।

এখন আপনি আপনার CSS-এ সেই ক্লাসের নাম ব্যবহার করে ট্রানজিশন পরিবর্তন করতে পারেন:

/* '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;
}

আর এটাই!

ভিডিও ট্রানজিশন, ধীর। ন্যূনতম ডেমোউৎস

এখন ভিডিওটি পুরো রূপান্তর জুড়ে চলতে থাকে।


নেভিগেশন এপিআই (এবং অন্যান্য ফ্রেমওয়ার্ক) এর সাথে ইন্টিগ্রেশন

ভিউ ট্রানজিশনগুলি এমনভাবে নির্দিষ্ট করা হয় যাতে সেগুলি অন্যান্য ফ্রেমওয়ার্ক বা লাইব্রেরির সাথে একীভূত করা যায়। উদাহরণস্বরূপ, যদি আপনার একক-পৃষ্ঠা অ্যাপ্লিকেশন (SPA) একটি রাউটার ব্যবহার করে, তাহলে আপনি ভিউ ট্রানজিশন ব্যবহার করে কন্টেন্ট আপডেট করার জন্য রাউটারের আপডেট প্রক্রিয়াটি সামঞ্জস্য করতে পারেন।

এই পেজিনেশন ডেমো থেকে নেওয়া নিম্নলিখিত কোড স্নিপেটে, ভিউ ট্রানজিশন সমর্থিত হলে নেভিগেশন 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 এর জন্য (বামে) এবং প্রস্থে (ডানে) একটি চেক ছাড়াই একই সাইটের তুলনা

জাভাস্ক্রিপ্ট দিয়ে অ্যানিমেটিং

এখন পর্যন্ত, সমস্ত ট্রানজিশন CSS ব্যবহার করে সংজ্ঞায়িত করা হয়েছে, কিন্তু কখনও কখনও CSS যথেষ্ট হয় না:

বৃত্ত পরিবর্তন। ন্যূনতম ডেমোউৎস

এই রূপান্তরের কয়েকটি অংশ কেবল CSS দিয়ে অর্জন করা সম্ভব নয়:

  • অ্যানিমেশনটি ক্লিকের অবস্থান থেকে শুরু হয়।
  • অ্যানিমেশনটি বৃত্তের শেষ কোণে ব্যাসার্ধ দিয়ে শেষ হয়। যদিও, আশা করি ভবিষ্যতে CSS এর মাধ্যমে এটি সম্ভব হবে।

সৌভাগ্যক্রমে, আপনি ওয়েব অ্যানিমেশন 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 ব্যবহার করা হয়েছে, একটি প্রতিশ্রুতি যা ট্রানজিশন সিউডো-এলিমেন্টগুলি সফলভাবে তৈরি হওয়ার পরে সমাধান হয়ে যায়। এই অবজেক্টের অন্যান্য বৈশিষ্ট্যগুলি API রেফারেন্সে অন্তর্ভুক্ত করা হয়েছে।


একটি বর্ধন হিসাবে রূপান্তর

ভিউ ট্রানজিশন এপিআই একটি DOM পরিবর্তন 'র‍্যাপ' করার জন্য এবং এর জন্য একটি ট্রানজিশন তৈরি করার জন্য ডিজাইন করা হয়েছে। তবে, ট্রানজিশনটিকে একটি বর্ধিতকরণ হিসাবে বিবেচনা করা উচিত, যেমন, 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() প্রত্যাখ্যান করবে, কিন্তু এর অর্থ এই নয় যে ভিউটি স্যুইচ করতে ব্যর্থ হয়েছে। DOM সফলভাবে আপডেট হতে পারে, কিন্তু ডুপ্লিকেট 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
  }
}

এই উদাহরণে DOM আপডেটের জন্য অপেক্ষা করার জন্য transition.updateCallbackDone ব্যবহার করা হয়েছে, এবং যদি এটি ব্যর্থ হয় তবে প্রত্যাখ্যান করা হয়েছে। যদি ট্রানজিশন ব্যর্থ হয় তবে switchView আর প্রত্যাখ্যান করে না, DOM আপডেট সম্পূর্ণ হলে এটি সমাধান করে এবং যদি এটি ব্যর্থ হয় তবে প্রত্যাখ্যান করে।

যদি আপনি চান যে নতুন ভিউ 'স্থির' হয়ে গেলে, যেমন কোনও অ্যানিমেটেড ট্রানজিশন সম্পন্ন হয়ে গেলে বা শেষ পর্যন্ত এড়িয়ে গেলে, 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) {
    return unsupported('skipTransition was set to true');
  }

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

  if (!ViewTransition || !("types" in ViewTransition.prototype)) {
    return unsupported('View Transitions with types are not supported in this browser');
  }

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

  return transition;
}

এবং এটি এভাবে ব্যবহার করা যেতে পারে:

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

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

  // …
}

যেসব ব্রাউজার ভিউ ট্রানজিশন সমর্থন করে না, সেখানে updateDOM কল করা হবে, কিন্তু অ্যানিমেটেড ট্রানজিশন থাকবে না।

আপনি ট্রানজিশনের সময় <html> এ কিছু classNames যোগ করতে পারেন, যা নেভিগেশনের ধরণের উপর নির্ভর করে ট্রানজিশন পরিবর্তন করা সহজ করে তোলে।

যদি আপনি অ্যানিমেশন না চান, তাহলে আপনি true কে skipTransition এও পাস করতে পারেন, এমনকি ভিউ ট্রানজিশন সমর্থনকারী ব্রাউজারেও। যদি আপনার সাইটের ট্রানজিশন অক্ষম করার জন্য ব্যবহারকারীর পছন্দ থাকে তবে এটি কার্যকর।


ফ্রেমওয়ার্ক নিয়ে কাজ করা

যদি আপনি এমন কোনও লাইব্রেরি বা ফ্রেমওয়ার্ক নিয়ে কাজ করেন যা DOM পরিবর্তনগুলি সারাংশ করে, তাহলে জটিল অংশটি হল DOM পরিবর্তনটি কখন সম্পূর্ণ হবে তা জানা। এখানে বিভিন্ন ফ্রেমওয়ার্কে উপরে সাহায্যকারী ব্যবহার করে কিছু উদাহরণ দেওয়া হল।

  • React — এখানে মূল কথা হল flushSync , যা সিঙ্ক্রোনাসভাবে কিছু স্টেট পরিবর্তন প্রয়োগ করে। হ্যাঁ, এই API ব্যবহার করার ক্ষেত্রে একটি বড় সতর্কতা রয়েছে, তবে ড্যান আব্রামভ আমাকে আশ্বস্ত করেছেন যে এই ক্ষেত্রে এটি উপযুক্ত। React এবং async কোডের ক্ষেত্রে যথারীতি, startViewTransition দ্বারা প্রদত্ত বিভিন্ন প্রতিশ্রুতি ব্যবহার করার সময়, খেয়াল রাখবেন যে আপনার কোডটি সঠিক স্টেটে চলছে।
  • Vue.js — এখানে মূল কথা হল nextTick , যা DOM আপডেট হওয়ার পরে পূরণ হয়।
  • Svelte — Vue-এর মতোই, কিন্তু পরবর্তী পরিবর্তনের জন্য অপেক্ষা করার পদ্ধতি হল tick
  • আলো — এখানে মূল কথা হল কম্পোনেন্টের মধ্যে this.updateComplete প্রতিশ্রুতি, যা DOM আপডেট হওয়ার পরে পূরণ হয়।
  • Angular — এখানে মূল কথা হল applicationRef.tick , যা DOM পরিবর্তনগুলি স্থগিত করে। Angular সংস্করণ 17 থেকে আপনি withViewTransitions ব্যবহার করতে পারেন যা @angular/router এর সাথে আসে

API রেফারেন্স

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 পরিবর্তন মোড়ানো এবং একটি রূপান্তর তৈরি করে। তবে, কখনও কখনও আপনি রূপান্তর অ্যানিমেশনের সাফল্য বা ব্যর্থতা নিয়ে চিন্তা করেন না, আপনি কেবল জানতে চান যে DOM পরিবর্তন কখন এবং কখন ঘটে। updateCallbackDone সেই ব্যবহারের ক্ষেত্রে।

viewTransition.ready

একটি প্রতিশ্রুতি যা রূপান্তরের জন্য ছদ্ম-উপাদান তৈরি হয়ে গেলে এবং অ্যানিমেশন শুরু হতে চলেছে, তা পূরণ করে।

যদি ট্রানজিশন শুরু না হয় তাহলে এটি প্রত্যাখ্যান করে। এটি ভুল কনফিগারেশনের কারণে হতে পারে, যেমন ডুপ্লিকেট view-transition-name s, অথবা updateCallback যদি একটি প্রত্যাখ্যাত প্রতিশ্রুতি ফেরত দেয়।

এটি জাভাস্ক্রিপ্ট দিয়ে ছদ্ম-উপাদানের রূপান্তর অ্যানিমেট করার জন্য কার্যকর।

viewTransition.finished

একটি প্রতিশ্রুতি যা ব্যবহারকারীর কাছে শেষ অবস্থা সম্পূর্ণরূপে দৃশ্যমান এবং ইন্টারেক্টিভ হওয়ার পরে পূরণ হয়।

এটি শুধুমাত্র তখনই প্রত্যাখ্যান করে যদি updateCallback একটি প্রত্যাখ্যাত প্রতিশ্রুতি ফেরত দেয়, কারণ এটি নির্দেশ করে যে শেষ অবস্থা তৈরি করা হয়নি।

অন্যথায়, যদি একটি রূপান্তর শুরু হতে ব্যর্থ হয়, অথবা রূপান্তরের সময় এড়িয়ে যায়, তবুও শেষ অবস্থায় পৌঁছানো যায়, তাই finished পূর্ণ হয়।

viewTransition.types

একটি Set -জাতীয় অবজেক্ট যা সক্রিয় ভিউ ট্রানজিশনের ধরণ ধারণ করে। এন্ট্রিগুলি পরিচালনা করতে, এর ইনস্ট্যান্স পদ্ধতিগুলি clear() , add() , এবং delete() ব্যবহার করুন।

CSS-এ একটি নির্দিষ্ট ধরণের প্রতিক্রিয়া জানাতে, ট্রানজিশন রুটে :active-view-transition-type(type) pseudo-class নির্বাচক ব্যবহার করুন।

ভিউ ট্রানজিশন শেষ হলে টাইপগুলি স্বয়ংক্রিয়ভাবে পরিষ্কার হয়ে যায়।

viewTransition.skipTransition()

ট্রানজিশনের অ্যানিমেশন অংশটি এড়িয়ে যান।

এটি updateCallback কল করা এড়িয়ে যাবে না, কারণ DOM পরিবর্তনটি ট্রানজিশন থেকে আলাদা।


ডিফল্ট স্টাইল এবং ট্রানজিশন রেফারেন্স

::view-transition
রুট সিউডো-এলিমেন্ট যা ভিউপোর্ট পূরণ করে এবং প্রতিটি ::view-transition-group ধারণ করে।
::view-transition-group

একেবারে ঠিক অবস্থানে।

'আগে' এবং 'পরে' অবস্থার মধ্যে width এবং height পরিবর্তন করে।

'আগে' এবং 'পরে' ভিউপোর্ট-স্পেস কোয়াডের মধ্যে রূপান্তরগুলি transform

::view-transition-image-pair

দলটি পূরণ করার জন্য একেবারে উপযুক্ত।

isolation: isolate পুরাতন এবং নতুন ভিউয়ের উপর mix-blend-mode প্রভাব সীমিত করতে আইসোলেশন।

::view-transition-new এবং ::view-transition-old

একেবারে মোড়কের উপরের বাম দিকে অবস্থিত।

গ্রুপের প্রস্থের ১০০% পূরণ করে, কিন্তু এর উচ্চতা স্বয়ংক্রিয়, তাই এটি গ্রুপটি পূরণ করার পরিবর্তে এর আকৃতির অনুপাত বজায় রাখবে।

mix-blend-mode: plus-lighter যাতে সত্যিকারের ক্রস-ফেড তৈরি হয়।

পুরাতন ভিউ opacity: 1 থেকে opacity: 0 তে রূপান্তরিত হয়। নতুন ভিউ opacity: 0 থেকে opacity: 1 তে রূপান্তরিত হয়।


প্রতিক্রিয়া

ডেভেলপারদের প্রতিক্রিয়া সর্বদা প্রশংসনীয়। এটি করার জন্য, পরামর্শ এবং প্রশ্ন সহ GitHub-এর CSS ওয়ার্কিং গ্রুপে একটি সমস্যা দায়ের করুন[css-view-transitions] দিয়ে আপনার সমস্যার প্রিফিক্সটি পূরণ করুন।

যদি আপনি কোন বাগের সম্মুখীন হন, তাহলে পরিবর্তে একটি Chromium বাগ ফাইল করুন