用途
實現檢視過渡效果
示例1
實現兩張圖片之間的過渡效果
<script setup lang="ts">
import { ref } from "vue"
const visible = ref(false)
const toggle = () => {
// 關鍵程式碼,把扭轉狀態的程式碼用startViewTransition包起來
document.startViewTransition(() => {
visible.value = !visible.value
})
}
</script>
<template>
<img v-if="!visible"
class="small-img"
src="https://live.staticflickr.com/65535/50187927333_12dc192ab6_b.jpg"
@click="toggle">
<img v-if="visible"
class="big-img"
src="https://live.staticflickr.com/65535/50187927333_12dc192ab6_b.jpg"
@click="toggle">
</template>
<style>
.small-img {
width: 500px;
}
.big-img {
width: 1000px;
}
</style>
startViewTransition的預設效果是對新舊檢視進行fade-in和fade-out動畫過渡,也就是opacity的0和1過渡。
示例2
縮放過渡
<script setup lang="ts">
import { ref } from "vue"
const visible = ref(false)
const toggle = () => {
document.startViewTransition(() => {
visible.value = !visible.value
})
}
</script>
<template>
<img v-if="!visible"
class="small-img"
src="https://live.staticflickr.com/65535/50187927333_12dc192ab6_b.jpg"
@click="toggle">
<img v-if="visible"
class="big-img"
src="https://live.staticflickr.com/65535/50187927333_12dc192ab6_b.jpg"
@click="toggle">
</template>
<style>
.small-img {
width: 500px;
// 關鍵程式碼 定義過渡名稱
view-transition-name: img;
}
.big-img {
width: 1000px;
// 關鍵程式碼 定義過渡名稱
view-transition-name: img;
}
</style>
實現該效果的關鍵程式碼是.small-img和.big-img上定義的view-transition-name: img,這裡的程式碼是告訴瀏覽器,幫我對view-transition-name為img的元素進行動畫過渡。然後瀏覽器會對兩個設定為同樣view-transition-name的元素進行動畫過渡。
需要注意的是,在同一個dom樹中,不能同時存在兩個view-transition-name相同的元素,所以你會看到上面的示例程式碼中使用visible進行了判斷。
示例3
路由過渡
路由配置如下:
const routes = [
{
path: "/before",
component: before,
},
{
path: "/after",
component: after,
},
]
/before路由內容
<script setup lang="ts">
import { useRouter } from "vue-router"
const router = useRouter()
const handleClick = () => {
document.startViewTransition(() => {
router.push('/photos/1')
})
}
</script>
<template>
<img
class="photo"
src="https://live.staticflickr.com/65535/50187927333_12dc192ab6_b.jpg"
alt="photo"
@click="handleClick"
/>
</template>
<style scoped>
.photo {
width: 400px;
// 關鍵程式碼 定義過渡名稱
view-transition-name: photo;
}
</style>
/after路由內容
<script setup lang="ts">
import { useRouter } from "vue-router"
const router = useRouter()
const handleClick = () => {
document.startViewTransition(() => {
router.push('/before')
})
}
</script>
<template>
<img
class="photo"
src="https://live.staticflickr.com/65535/50187927333_12dc192ab6_b.jpg"
alt="photo"
@click="handleClick"
/>
</template>
<style scoped>
.photo {
max-width: 100%;
// 關鍵程式碼 定義過渡名稱
view-transition-name: photo;
}
</style>
兩個路由中的img元素宣告瞭相同的view-transition-name,然後瀏覽器就對其進行了動畫過渡。
示例4
列表與詳情路由的過渡
/articles路由
<script setup lang="ts">
import { ref } from "vue"
import { useRouter } from "vue-router";
import { photos as photosData } from "@/api";
const router = useRouter()
const photos = ref(photosData)
const handleClick = (id: number) => {
document.startViewTransition(() => {
router.push(`/articles/${id}`)
})
}
</script>
<template>
<div class="container">
<div class="items">
<div
class="item"
v-for="photo in photos"
:key="photo.id"
@click="handleClick(photo.id)"
>
<img
class="img"
:src="photo.src"
:alt="photo.alt"
:style="`view-transition-name: photo-${photo.id}`" />
<div
:style="`view-transition-name: title-${photo.id}`"
>{{ photo.alt }}</div>
</div>
</div>
</div>
</template>
<style scoped>
body {
background: #f7f7f8;
}
.container {
display: flex;
justify-content: center;
align-items: center;
}
.items {
display: flex;
flex-direction: column;
margin-top: 20px;
}
.item {
display: block;
margin-bottom: 20px;
width: 400px;
padding: 15px;
border-radius: 3px;
background: #fff;
}
.img {
width: 100%;
margin-bottom: 5px;
}
</style>
/articles/:id路由
<script setup lang="ts">
import { computed } from "vue";
import { useRouter } from "vue-router";
import { useRoute } from "vue-router"
import { photos } from "@/api";
const router = useRouter()
const route = useRoute()
const id = route.params.id as string
const data = computed(() => photos.find((photo) => photo.id === Number(id)))
const handleBack = () => {
document.startViewTransition(() => {
router.push("/articles")
})
}
</script>
<template>
<div class="container" @click.self="handleBack">
<img
class="img"
:src="data?.src"
:style="`view-transition-name: photo-${id}`" />
<div
class="title"
:style="`view-transition-name: title-${id}`"
>{{ data?.alt }}</div>
<button @click="handleBack">返回</button>
</div>
</template>
<style scoped>
.container {
display: flex;
flex-direction: column;
align-items: center;
}
.img {
width: 1000px;
}
.title {
padding: 20px 0;
font-size: 20px;
font-weight: bold;
}
</style>
實現該效果的關鍵程式碼是.img元素上的view-transition-name: photo-${id}和.title元素上的view-transition-name: title-${id},由於同一個頁面不能有相同的view-transition-name存在,所以在這種列表過渡的情況下,我們用id給每個元素作區分。