用途
实现视图过渡效果
示例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给每个元素作区分。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。