本文仅仅自己备份使用
html
<button @click="handleClick" class="theme-toggle-btn" :class="{ dark: currentTheme === 'dark' }" aria-label="Toggle theme">
<span class="sun-icon">☀️</span>
<span class="moon-icon"></span>
</button>
// currentTheme是light和dark
// switchTheme是切换主题逻辑
import { currentTheme, switchTheme, } from "../utils/theme"
const handleClick = (event) => {
if (!document.startViewTransition) {
switchTheme()
return
}
const x = event.clientX
const y = event.clientY
const endRadius = Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y)
)
const transition = document.startViewTransition(() => {
switchTheme()
})
transition.ready.then(() => {
const clipPath = [`circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`]
document.documentElement.animate(
{
clipPath: currentTheme.value === "dark" ? [...clipPath].reverse() : clipPath
},
{
duration: 500,
easing: 'ease-in',
pseudoElement: currentTheme.value === "dark" ? "::view-transition-old(root)" : "::view-transition-new(root)"
}
)
})
}
scss
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
::view-transition-old(root) {
z-index: 1;
}
::view-transition-new(root) {
z-index: 2147483646;
}
.dark::view-transition-old(root) {
z-index: 2147483646;
}
.dark::view-transition-new(root) {
z-index: 1;
}
root {
--bg-light: #f5f5f5;
--text-light: #333;
--bg-dark: #1a1a1a;
--text-dark: #f0f0f0;
}
body {
background: var(--bg-light);
color: var(--text-light);
transition: background 0.3s, color 0.3s;
}
.dark body {
background: var(--bg-dark);
color: var(--text-dark);
}
.theme-toggle-btn {
position: relative;
width: 48px;
height: 24px;
border-radius: 12px;
background: var(--bg-light);
border: none;
cursor: pointer;
transition: background 0.3s;
}
.theme-toggle-btn.dark {
background: var(--bg-dark);
}
.sun-icon, .moon-icon {
position: absolute;
top: 2px;
transition: all 0.3s ease;
}
.sun-icon {
left: 2px;
opacity: 1;
}
.moon-icon {
right: 2px;
opacity: 0;
}
.dark .sun-icon {
opacity: 0;
}
.dark .moon-icon {
opacity: 1;
}