如何在Vuetify中实现主题切换的圆形扩散动画效果?
问题解答
这个从点击位置展开的圆形主题切换动画并非Vuetify的内置功能,是Vuetify官网自行实现的自定义过渡效果。以下是复现该效果的具体方案:
实现思路
核心逻辑是通过一个临时的圆形覆盖层,从点击位置展开覆盖全屏,同步完成主题切换,模拟官网的动画效果:
- 捕获主题切换按钮的点击坐标
- 创建一个圆形元素,定位到点击位置,初始尺寸为0
- 通过CSS动画让圆形元素放大至覆盖整个视口
- 动画结束后切换Vuetify主题,并清理临时元素
代码实现示例
Vue组件结构
<template> <div> <!-- 主题切换按钮 --> <v-btn @click="triggerThemeSwitch" variant="flat">切换主题</v-btn> <!-- 动画覆盖层 --> <div ref="themeOverlay" class="theme-overlay"></div> </div> </template>
脚本逻辑
<script setup> import { ref } from 'vue' import { useTheme } from 'vuetify' const theme = useTheme() const themeOverlay = ref(null) const triggerThemeSwitch = (e) => { // 获取点击位置的坐标 const { clientX, clientY } = e const overlay = themeOverlay.value // 确定目标主题的背景色(可替换为主色等其他主题颜色) const targetBgColor = theme.global.name.value === 'light' ? theme.global.current.value.background : theme.global.current.value.background // 初始化覆盖层的位置与样式 overlay.style.left = `${clientX}px` overlay.style.top = `${clientY}px` overlay.style.backgroundColor = targetBgColor // 触发展开动画 overlay.classList.add('animate-expand') // 动画结束后执行主题切换并清理 const onAnimationEnd = () => { // 切换Vuetify主题 theme.global.name.value = theme.global.name.value === 'light' ? 'dark' : 'light' // 重置覆盖层状态 overlay.classList.remove('animate-expand') overlay.removeEventListener('animationend', onAnimationEnd) } overlay.addEventListener('animationend', onAnimationEnd) } </script>
CSS样式
<style scoped> .theme-overlay { position: fixed; border-radius: 50%; width: 0; height: 0; transform: translate(-50%, -50%); z-index: 9999; /* 确保覆盖层在最上层 */ pointer-events: none; /* 避免遮挡交互 */ transition: none; } .animate-expand { animation: expand 0.6s cubic-bezier(0.25, 1, 0.5, 1) forwards; } /* 定义圆形展开动画 */ @keyframes expand { to { width: 200vmax; height: 200vmax; } } </style>
自定义调整建议
- 可以修改
animation属性中的时长(0.6s)或缓动函数(cubic-bezier)来调整动画节奏 - 替换
targetBgColor的取值,比如使用主题的主色(theme.global.current.value.primary)来实现不同的视觉效果 - 如果需要更平滑的过渡,可以在主题切换后添加元素样式的淡入淡出效果
内容的提问来源于stack exchange,提问作者Shadow
相关产品推荐
相关产品推荐

