اجرای انتقال‌های نمای همزمان و تودرتو با انتقال‌های نمای محدود به عنصر

منتشر شده: ۲۷ مارس ۲۰۲۶

انتقال‌های نمای محدود به عنصر، امکان اجرای همزمان چندین انتقال نمای دیگر را فراهم می‌کنند، امکان تودرتو کردن انتقال‌های نمای جاری را در یکدیگر فراهم می‌کنند و مشکلات z-index را که ممکن است با انتقال‌های نمای محدود به سند با آنها مواجه شوید، برطرف می‌کنند - همه اینها در حالی است که بقیه صفحه تعاملی باقی می‌ماند. برای یادگیری نحوه استفاده از آنها، این راهنما را بخوانید.

ویدیوی تبلیغاتی: با Scoped View Transitions، وب را از نو تصور کنید. یک نسخه آزمایشی زنده را امتحان کنید (کروم ۱۴۷ یا بالاتر)

نیاز به گذارهای دید با دامنه محدودتر

وقتی یک گذار نمای سند-مشابه را با document.startViewTransition() (یا از طریق معادل بین سندی آن) شروع می‌کنید، مرورگر گذار نمای حاصل را به سند مورد نظر محدود می‌کند.

پس از اجرای تابع فراخوانی به‌روزرسانی و گرفتن عکس فوری از تمام عناصر لازم توسط مرورگر، لایه پوششی حاصل از ::view-transition و درخت شبه عناصر آن به عنصر :root ، در مثال زیر، html متصل می‌شوند.

html
  ├─ ::view-transition
  │  └─ ::view-transition-group(root)
  │     └─ ::view-transition-image-pair(root)
  │        ├─ ::view-transition-old(root)
  │        └─ ::view-transition-new(root)
  ├─ head
  └─ body
     └─ …

از آنجا که لایه ::view-transition روی ریشه گذار رندر می‌شود، این می‌تواند منجر به موقعیت‌های غیرمنتظره‌ای شود. برای مثال، عناصری که در گذار نما شرکت می‌کنند ممکن است ناگهان با عناصر غیرشرکت‌کننده همپوشانی داشته باشند، یا عناصر ممکن است دیگر توسط پوشش اجداد خود در طول گذار نما برش داده نشوند.

نسخه آزمایشی زنده

ضبط نسخه آزمایشی

فعال‌سازی مجدد pointer-events در ::view-transition یا استفاده از گروه‌های انتقال نمای تودرتو می‌تواند برخی از عوارض جانبی که انتقال‌های نمای سند-محدود ایجاد می‌کنند را برطرف کند. با این حال، این روش‌ها نمی‌توانند همه مشکلات را حل کنند.

برای مثال، عناصری که position: fixed یا popover دارند، در حالی که گذار فعال است، توسط گذار نمای محدود به سند، پنهان می‌شوند - که به عنوان مشکل z-index نیز شناخته می‌شود.

در دموی زیر، پنجره‌ی پاپ‌اوور را تغییر دهید و سپس دکمه‌ی Shuffle را انتخاب کنید تا یک گذار نمای سند-محدوده آغاز شود. گروه‌های گذار نمای تودرتو مشکل برش را حل می‌کنند، اما مشکل لایه‌بندی همچنان باقی است.

نسخه آزمایشی زنده

ضبط نسخه آزمایشی

یک راه حل این است که با دادن view-transition-name به popover ، آن را به عنوان بخشی از گذار نما ثبت کنیم. اگرچه این روش ممکن است برای یک نمونه‌ی واحد کار کند، اما نگهداری آن دشوار است و فرآیند ثبت لحظه‌ای را به طور غیرضروری تحت فشار قرار می‌دهد.

انتقال‌های نمای محدود به عنصر

انتقال‌های نمای محدود به عنصر به شما امکان می‌دهند یک انتقال نما را روی یک زیردرخت از DOM شروع کنید. به جای فراخوانی document.startViewTransition() ، شما element.startViewTransition() را روی یک عنصر دلخواه فراخوانی می‌کنید که انتقال نما را به آن عنصر محدود می‌کند.

در قطعه کد زیر، مرورگر یک گذار نمای محدود به عنصر را روی عنصر <ul> آغاز می‌کند.

document.querySelector('ul').startViewTransition({
  callback: () => {
    // … code that manipulates the contents of <ul>
  },
})

عنصری که در آن element.startViewTransition() را فراخوانی می‌کنید - برای مثال <ul> - ریشه گذار یا دامنه نامیده می‌شود.

وقتی مرورگر، گذار یک نما به یک عنصر را محدود می‌کند، آن عنصر از بقیه DOM جدا می‌شود:

  • مرورگر فقط عناصری را برای گرفتن عکس فوری در زیردرخت دامنه جستجو می‌کند.
  • در طول فرآیند snapshoting - در حالی که callback update اجرا می‌شود - فقط رندر کردن scope متوقف می‌شود.
  • شبه‌درخت حاصل ::view-transition به ریشه گذار تزریق می‌شود.

برای مثال، با <ul> ، درخت DOM در حالی که گذار نما فعال است، به این شکل به نظر می‌رسد:

html
  ├─ head
  └─ body
     ├─ ul
     │  ├─ ::view-transition
     │  │  └─ ::view-transition-group(root)
     │  │     ├─ ::view-transition-group-children(root)
     │  │     │  └─ …
     │  │     └─ ::view-transition-image-pair(root)
     │  │        ├─ ::view-transition-old(root)
     │  │        └─ ::view-transition-new(root)
     │  ├─ li
     │  ├─ li
     │  └─ li
     ├─ button#showpopover
     ├─ button#reorder
     └─ div#popover
        └─ p

شبه‌تابع ::view-transition اندازه و شکل یکسانی با ریشه transition دارد و فقط روی ریشه transition رندر می‌شود. به همین دلیل، ترتیب لایه‌بندی عناصر خارج از ریشه transition رعایت می‌شود.

برای مثال، اگر یک popover دارید که بالای عنصر <ul> قابل مشاهده است و سپس یک گذار نمای محدود به عنصر را روی عنصر <ul> شروع کنید، popover توسط شبه درخت گذار نمای پنهان نمی‌شود.

در دموی زیر، آن را امتحان کنید. دو دکمه دارد. دکمه‌ی اول، منوی پاپ‌اوور را فعال و غیرفعال می‌کند و دکمه‌ی دوم، با استفاده از یک گذار نمای محدود به عنصر، ترتیب آیتم‌های لیست را تغییر می‌دهد.

نسخه آزمایشی زنده

ضبط نسخه آزمایشی

از آنجا که از انتقال‌های نمای محدود به عنصر استفاده می‌شود، تا زمانی که انتقال فعال است، پاپ‌اوور در بالای عنصر <ul> قابل مشاهده باقی می‌ماند.

علاوه بر این، عناصر خارج از عنصر <ul> - برای مثال دکمه‌ها - همچنان تعاملی باقی می‌مانند، زیرا این عناصر بخشی از محدوده نیستند.

دامنه‌های خود-مشارکتی و گروه‌های انتقال نمای تودرتو

وقتی یک گذار نمای محدود به عنصر را روی عنصری که سرریز آن را قطع می‌کند (یعنی وقتی overflow آن روی hidden ، scroll یا clip تنظیم شده است) شروع می‌کنید، متوجه می‌شوید که محتوای گذار نمای از نظر بصری قطع شده باقی می‌ماند.

دلیل این امر این است که انتقال‌های نمای محدود به عنصر، موارد زیر را به طور خودکار مدیریت می‌کنند:

  • این دامنه به طور خودکار view-transition-name: root را دریافت می‌کند که آن را به صورت خود-مشارکتی (self-participating) در می‌آورد.
  • این دامنه به طور خودکار view-transition-group: contain را دریافت می‌کند تا گروه‌های انتقال نمای تو در تو را فعال کند.
  • شبه‌برنامه‌ی حاصل ::view-transition-group-children(root) به طور خودکار محتویات خود را با استفاده از overflow: clip می‌دهد، اگر ریشه‌ی دامنه سرریز خود را برش دهد، که این امر مانع از آن می‌شود که شبه‌برنامه‌ها از نظر بصری از ریشه‌ی انتقال خارج شوند.

در نتیجه، می‌توانید CSS مورد استفاده در انتقال‌های نمای محدود به عنصر را فقط روی عناصری که می‌خواهید ضبط کنید متمرکز نگه دارید. برای مثال، در نسخه آزمایشی لیست، CSS فقط نام‌ها را به موارد لیست اضافه می‌کند:

ul li {
  view-transition-name: match-element;
  view-transition-class: album;
}

در دموی زیر، آن را امتحان کنید. این به شما امکان می‌دهد تا خود-مشارکتی را لغو کنید. وقتی دامنه خود-مشارکتی است (رفتار پیش‌فرض)، همه چیز طبق انتظار کار می‌کند. وقتی دامنه خود-مشارکتی نیست، حاشیه آن بلافاصله تغییر می‌کند و محتویات آن در طول انتقال از پوشش خارج می‌شوند.

نسخه آزمایشی زنده

ضبط نسخه آزمایشی

برای مرجع، شبه‌درخت این نسخه آزمایشی با مشارکت شخصی به این شکل است:

html
  ├─ head
  └─ body
     ├─ ul
     │  ├─ ::view-transition
     │  │  └─ ::view-transition-group(root)
     │  │     ├─ ::view-transition-group-children(root)
     │  │     │  ├─ ::view-transition-group(item1)
     │  │     │  │  └─ ::view-transition-image-pair(item1)
     │  │     │  │     ├─ ::view-transition-old(item1)
     │  │     │  │     └─ ::view-transition-new(item1)
     │  │     │  ├─ ::view-transition-group(item2)
     │  │     │  │  └─ …
     │  │     │  …
     │  │     └─ ::view-transition-image-pair(root)
     │  │        ├─ ::view-transition-old(root)
     │  │        └─ ::view-transition-new(root)
     │  ├─ li
     │  ├─ li
     │  └─ li
     └─ button#reorder

از آنجا که ریشه انتقال، یعنی عنصر <ul> ، محتویات خود را به صورت عمودی برش می‌دهد، تابع ::view-transition-group-children(root) ‎ نیز به طور خودکار برش را اعمال می‌کند.

انتقال‌های نمای همزمانِ محدود به عنصر

از آنجایی که انتقال‌های نمای محدود به عنصر به صورت جداگانه اجرا می‌شوند، چندین انتقال نمای محدود به عنصر می‌توانند در صورت داشتن دامنه متفاوت، همزمان اجرا شوند.

دموی زیر دو دکمه‌ی مرتب‌سازی مجدد دارد، یکی برای هر لیست. هر دکمه یک گذار نمای محدود به عنصر را فقط در لیست مربوطه‌اش آغاز می‌کند. از آنجا که درخت‌های DOM هر دو لیست با هم همپوشانی ندارند، دو گذار نمای محدود به عنصر می‌توانند همزمان و به صورت جداگانه اجرا شوند.

نسخه آزمایشی زنده

ضبط نسخه آزمایشی

این ماهیت ایزوله همچنین به شما امکان می‌دهد از مقادیر view-transition-name در محدوده‌های مختلف استفاده مجدد کنید. تا زمانی که یک نام در محدوده خود منحصر به فرد باقی بماند، هیچ تداخلی وجود ندارد.

انتقال‌های نمای محدود به عنصر تو در تو و مهار نام انتقال نمای

وقتی درخت‌های DOM مربوط به چندین گذار نمای محدود به عنصر با هم همپوشانی دارند، خطر تصادم مقدار view-transition-name وجود دارد. به همین دلیل، مرورگر به طور خودکار view-transition-scope: all به گذارهای نمای محدود به عنصر فعال اختصاص می‌دهد تا این خطر را کاهش دهد.

مشابه نحوه‌ی اعمال محدودیت بر مقادیر anchor-name anchor-scope ، ویژگی view-transition-scope تضمین می‌کند که مقادیر view-transition-name به زیردرخت عنصر اعمال شوند. این ویژگی مقدار none ، لیستی از نام‌هایی که می‌خواهید اعمال شوند، یا all را برای اعمال محدودیت بر همه‌ی مقادیر می‌پذیرد.

علاوه بر جلوگیری از بیرون زدن نام‌ها، view-transition-scope همچنین از ضبط یک عنصر و محتویات آن توسط یک انتقال نمای خارجی و همزمان جلوگیری می‌کند. هنگامی که فرآیند snapshoting زیردرخت را برای یافتن عنصری برای snapshot پیمایش می‌کند، عناصری (و کل زیردرخت آنها) را که view-transition-scope: all آنها اعمال شده است، نادیده می‌گیرد. این فرض را بر این می‌گذارد که آن عناصر از قبل در یک انتقال نمای با محدوده عنصر متفاوت شرکت می‌کنند.

دموی زیر نسخه‌ی تغییر یافته‌ی دموی قبلی است. علاوه بر دو دکمه‌ای که محتوای لیست را جابجا می‌کنند، یک دکمه‌ی Swap نیز برای جابجایی لیست‌ها دارد. فعال/غیرفعال کردن کلاس .reversed در #lists-wrapper جابجایی را مدیریت می‌کند.

نسخه آزمایشی زنده

ضبط نسخه آزمایشی

از آنجا که view-transition-scope: all به طور خودکار در طول انتقال shuffle اعمال می‌شود، می‌توانید یک انتقال swap بیرونی و همزمان را در حالی که انتقال shuffle هنوز در حال انجام است، شروع کنید.

از آنجا که view-transition-scope: all همچنین از snapshot شدن یک عنصر در یک transition بیرونی جلوگیری می‌کند، این نسخه آزمایشی مقادیر view-transition-name را به عناصری که عناصر <ul> را در بر می‌گیرند نیز اضافه می‌کند.

#list1-wrapper, #list2-wrapper {
  view-transition-name: attr(id type(<custom-ident>));
}

شبه‌درخت این نسخه آزمایشی، پس از شروع عملیات بُر زدن در لیست دوم و سپس جابجایی هر دو لیست، به شکل زیر خواهد بود:

html
  ├─ head
  └─ body
     └─ #lists-wrapper.reversed (SCOPE)
        ├─ ::view-transition
        │  └─ ::view-transition-group(lists-wrapper)
        │     ├─ ::view-transition-group-children(lists-wrapper)
        │     │  ├─ ::view-transition-group(list1-wrapper)
        │     │  │  └─ ::view-transition-image-pair(list1-wrapper)
        │     │  │     ├─ ::view-transition-old(list1-wrapper)
        │     │  │     └─ ::view-transition-new(list1-wrapper)
        │     │  └─ ::view-transition-group(list2-wrapper)
        │     │     └─ ::view-transition-image-pair(list2-wrapper)
        │     │        ├─ ::view-transition-old(list2-wrapper)
        │     │        └─ ::view-transition-new(list2-wrapper)
        │     └─ ::view-transition-image-pair(lists-wrapper)
        │        ├─ ::view-transition-old(lists-wrapper)
        │        └─ ::view-transition-new(lists-wrapper)
        ├─ div#list1-wrapper
        │  ├─ ul
        │  │  ├─ li#item1
        │  │  ├─ li#item2
        │  │  └─ li#item3
        │  └─ button.reorder
        └─ div#list2-wrapper
           ├─ ul (SCOPE)
           │  ├─ ::view-transition
           │  │  └─ ::view-transition-group(list)
           │  │     ├─ ::view-transition-group-children(list    )
           │  │     │  ├─ ::view-transition-group(item4)
           │  │     │  │  └─ ::view-transition-image-pair(item4)
           │  │     │  │     ├─ ::view-transition-old(item4)
           │  │     │  │     └─ ::view-transition-new(item4)
           │  │     │  ├─ ::view-transition-group(item5)
           │  │     │  │  └─ …
           │  │     │  …
           │  │     └─ ::view-transition-image-pair(list)
           │  │        ├─ ::view-transition-old(list)
           │  │        └─ ::view-transition-new(list)
           │  ├─ li#item4
           │  ├─ li#item5
           │  └─ li#item6
           └─ button.reorder

بیشتر بدانید

برای کسب اطلاعات بیشتر در مورد انتقال‌های نمای محدود به عنصر، به explainer ، مشخصات css-view-transitions-2 و فهرست ویرایش‌های مشخصات باز مراجعه کنید.