好的,我帮你写一个 Vue 3 + Vue Router 4 + View Transition API 的简单示例,实现点击按钮从一个路由跳到另一个路由,同时带圆形扩散动画。


1. 安装和初始化 Vue 3 + Vue Router 4

npm init vite@latest vue-view-transition -- --template vue
cd vue-view-transition
npm install
npm install vue-router@4

2. 设置路由

// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About }
]

export const router = createRouter({
  history: createWebHistory(),
  routes
})

3. Vue 根组件

<!-- src/App.vue -->
<template>
  <div id="app">
    <nav>
      <button @click="goRoute('/')">Home</button>
      <button @click="goRoute('/about')">About</button>
    </nav>
    <div id="view-container">
      <router-view />
    </div>
  </div>
</template>

<script setup lang="ts">
import { router } from './router'

function goRoute(path: string, event?: MouseEvent) {
  // 获取点击坐标
  const clientX = event?.clientX ?? window.innerWidth / 2
  const clientY = event?.clientY ?? window.innerHeight / 2

  // 设置 CSS 变量
  const maxRadius = Math.hypot(
    Math.max(clientX, window.innerWidth - clientX),
    Math.max(clientY, window.innerHeight - clientY)
  )
  document.documentElement.style.setProperty('--v3-theme-x', `${clientX}px`)
  document.documentElement.style.setProperty('--v3-theme-y', `${clientY}px`)
  document.documentElement.style.setProperty('--v3-theme-r', `${maxRadius}px`)

  // 使用 View Transition API 跳转路由
  if (document.startViewTransition) {
    document.startViewTransition(() => {
      router.push(path)
    })
  } else {
    router.push(path)
  }
}
</script>

<style>
#view-container {
  position: relative;
  overflow: hidden;
}

/* View Transition CSS */
::view-transition-old(#view-container) {
  animation: none;
  mix-blend-mode: normal;
}

::view-transition-new(#view-container) {
  animation: 0.5s ease-in clip-animation;
  mix-blend-mode: normal;
}

@keyframes clip-animation {
  from {
    clip-path: circle(0px at var(--v3-theme-x) var(--v3-theme-y));
  }
  to {
    clip-path: circle(var(--v3-theme-r) at var(--v3-theme-x) var(--v3-theme-y));
  }
}
</style>

4. 示例页面

<!-- src/views/Home.vue -->
<template>
  <div class="page home">
    <h1>Home Page</h1>
  </div>
</template>

<style>
.page {
  width: 100%;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  background-color: #f5f5f5;
}

.home { background-color: #f5f5f5; }
</style>
<!-- src/views/About.vue -->
<template>
  <div class="page about">
    <h1>About Page</h1>
  </div>
</template>

<style>
.about { background-color: #cce7ff; }
</style>

5. 关键点说明

  1. CSS 变量 --v3-theme-x / --v3-theme-y / --v3-theme-r

    • 控制动画圆心和半径。
  2. View Transition API

    • document.startViewTransition 捕获旧视图 → 执行 router.push() → 新视图应用动画。
  3. 圆形扩散动画

    • clip-path: circle() + @keyframes clip-animation 实现圆形从点击点扩张覆盖整个视图。
  4. 兼容性

    • 不支持 View Transition 的浏览器直接跳转,不会报错。

这就是一个最简单的 点击路由按钮 → 从点击点扩散 → 跳页动画 示例。

如果你愿意,我可以帮你改造成 鼠标点击位置自然扩散 + 任意路由组件动态过渡 的完整版本,让动画更平滑。

你希望我改造吗?

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐