> ## Documentation Index
> Fetch the complete documentation index at: https://inertiajs-vi.tuantq.online/llms.txt
> Use this file to discover all available pages before exploring further.

# View Transition

<Warning>Bạn đang xem tài liệu Inertia.js v2. Inertia.js v3 đã được phát hành và hiện là phiên bản mặc định. Hãy xem [hướng dẫn nâng cấp](/v3/getting-started/upgrade-guide) để bắt đầu.</Warning>

<Badge>v2.2.13+</Badge>

Inertia hỗ trợ [View Transitions API](https://developer.chrome.com/docs/web-platform/view-transitions), cho phép tạo animation khi chuyển trang.

View Transitions API là [tính năng trình duyệt tương đối mới](https://caniuse.com/view-transitions). Với trình duyệt không hỗ trợ API này, Inertia tự động fallback về chuyển trang tiêu chuẩn một cách an toàn.

## Bật transition

Bạn có thể bật view transition cho một visit bằng cách đặt tùy chọn `viewTransition` thành `true`. Mặc định, một hiệu ứng cross-fade sẽ được áp dụng giữa các trang.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.visit('/another-page', { viewTransition: true })
  ```

  ```js React icon="react" theme={null}
  import { router } from '@inertiajs/react'

  router.visit('/another-page', { viewTransition: true })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.visit('/another-page', { viewTransition: true })
  ```
</CodeGroup>

## Callback transition

Bạn cũng có thể truyền callback vào tùy chọn `viewTransition`; callback nhận instance [`ViewTransition`](https://developer.mozilla.org/en-US/docs/Web/API/ViewTransition) tiêu chuẩn do trình duyệt cung cấp. Điều này cho phép bạn hook vào các promise khác nhau của API.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from '@inertiajs/vue3'

  router.visit('/another-page', {
      viewTransition: (transition) => {
          transition.ready.then(() => console.log('Transition ready'))
          transition.updateCallbackDone.then(() => console.log('DOM updated'))
          transition.finished.then(() => console.log('Transition finished'))
      },
  })
  ```

  ```js React icon="react" theme={null}
  import { router } from '@inertiajs/react'

  router.visit('/another-page', {
      viewTransition: (transition) => {
          transition.ready.then(() => console.log('Transition ready'))
          transition.updateCallbackDone.then(() => console.log('DOM updated'))
          transition.finished.then(() => console.log('Transition finished'))
      },
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from '@inertiajs/svelte'

  router.visit('/another-page', {
      viewTransition: (transition) => {
          transition.ready.then(() => console.log('Transition ready'))
          transition.updateCallbackDone.then(() => console.log('DOM updated'))
          transition.finished.then(() => console.log('Transition finished'))
      },
  })
  ```
</CodeGroup>

## Liên kết

Tùy chọn `viewTransition` cũng có trên component `Link`.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  import { Link } from '@inertiajs/vue3'

  <Link href="/another-page" view-transition>Navigate</Link>
  ```

  ```jsx React icon="react" theme={null}
  import { Link } from '@inertiajs/react'

  <Link href="/another-page" viewTransition>Navigate</Link>
  ```

  ```svelte Svelte icon="s" theme={null}
  import { Link } from '@inertiajs/svelte'

  <Link href="/another-page" viewTransition>Navigate</Link>
  ```
</CodeGroup>

Bạn cũng có thể truyền callback để truy cập instance `ViewTransition`.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  import { Link } from '@inertiajs/vue3'

  <Link
      href="/another-page"
      :view-transition="(transition) => transition.finished.then(() => console.log('Done'))"
  >
      Navigate
  </Link>
  ```

  ```jsx React icon="react" theme={null}
  import { Link } from '@inertiajs/react'

  <Link
      href="/another-page"
      viewTransition={(transition) => transition.finished.then(() => console.log('Done'))}
  >
      Navigate
  </Link>
  ```

  ```svelte Svelte icon="s" theme={null}
  import { Link } from '@inertiajs/svelte'

  <Link
      href="/another-page"
      viewTransition={(transition) => transition.finished.then(() => console.log('Done'))}
  >
      Navigate
  </Link>
  ```
</CodeGroup>

## Cấu hình toàn cục

Bạn có thể bật view transition toàn cục cho mọi visit bằng cách cấu hình callback `visitOptions` khi [khởi tạo ứng dụng Inertia](/v2/installation/client-side-setup#configuring-defaults).

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { createInertiaApp } from '@inertiajs/vue3'

  createInertiaApp({
      // ...
      defaults: {
          visitOptions: (href, options) => {
              return { viewTransition: true }
          },
      },
  })
  ```

  ```jsx React icon="react" theme={null}
  import { createInertiaApp } from '@inertiajs/react'

  createInertiaApp({
      // ...
      defaults: {
          visitOptions: (href, options) => {
              return { viewTransition: true }
          },
      },
  })
  ```

  ```js Svelte icon="s" theme={null}
  import { createInertiaApp } from '@inertiajs/svelte'

  createInertiaApp({
      // ...
      defaults: {
          visitOptions: (href, options) => {
              return { viewTransition: true }
          },
      },
  })
  ```
</CodeGroup>

## Tùy chỉnh transition

Bạn có thể tùy chỉnh animation chuyển trang bằng CSS. View Transitions API sử dụng một số pseudo-element mà bạn có thể target bằng CSS để tạo animation riêng. Các ví dụ sau được lấy từ [tài liệu Chrome](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#customize_the_transition).

```css theme={null}
@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;
}
```

Bạn cũng có thể animate từng element riêng lẻ giữa các trang bằng cách gán `view-transition-name` duy nhất. Ví dụ, bạn có thể animate avatar từ kích thước lớn trên trang profile xuống kích thước nhỏ trên dashboard.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  <!-- Profile.vue -->
  <template>
      <img src="/avatar.jpg" alt="User" class="avatar-large" />
  </template>

  <style>
  .avatar-large {
      view-transition-name: user-avatar;
      width: auto;
      height: 200px;
  }
  </style>

  <!-- Dashboard.vue -->
  <template>
      <img src="/avatar.jpg" alt="User" class="avatar-small" />
  </template>

  <style>
  .avatar-small {
      view-transition-name: user-avatar;
      width: auto;
      height: 40px;
  }
  </style>
  ```

  ```jsx React icon="react" theme={null}
  // Profile.jsx
  export default function Profile() {
      return <img src="/avatar.jpg" alt="User" className="avatar-large" />
  }

  // CSS
  .avatar-large {
      view-transition-name: user-avatar;
      width: auto;
      height: 200px;
  }

  // Dashboard.jsx
  export default function Dashboard() {
      return <img src="/avatar.jpg" alt="User" className="avatar-small" />
  }

  // CSS
  .avatar-small {
      view-transition-name: user-avatar;
      width: auto;
      height: 40px;
  }
  ```

  ```svelte Svelte icon="s" theme={null}
  <!-- Profile.svelte -->
  <img src="/avatar.jpg" alt="User" class="avatar-large" />

  <style>
  .avatar-large {
      view-transition-name: user-avatar;
      width: auto;
      height: 200px;
  }
  </style>

  <!-- Dashboard.svelte -->
  <img src="/avatar.jpg" alt="User" class="avatar-small" />

  <style>
  .avatar-small {
      view-transition-name: user-avatar;
      width: auto;
      height: 40px;
  }
  </style>
  ```
</CodeGroup>

Bạn có thể tùy chỉnh view transition theo ý muốn bằng bất kỳ CSS animation nào. Để biết thêm, hãy xem [tài liệu View Transitions API](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#customize_the_transition).

***

## Tài liệu chính thức

Bài dịch này được đối chiếu từ [tài liệu Inertia.js v2 chính thức](https://inertiajs.com/docs/v2/the-basics/view-transitions). Nếu có khác biệt do phiên bản hoặc cập nhật mới, hãy ưu tiên tài liệu chính thức làm nguồn tham chiếu.
