Element Plus 的主题切换效果是一个非常精美的动画:点击主题按钮时,主题会从点击位置以圆形动画的形式扩散或收缩,为用户提供流畅的视觉体验。本文将介绍如何使用 Web API 中的 startViewTransition
实现这一效果。
实现代码
下面是实现 Element Plus 主题切换效果的完整代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Element Plus 主题切换效果</title>
<style>
* {
margin: 0;
padding: 0;
}
html {
background-color: white;
color: #303133;
transition: background-color 0.3s ease, color 0.3s ease;
}
html.dark {
background-color: #1a1a1a;
color: #f0f0f0;
}
button {
padding: 10px 20px;
margin: 20px;
background-color: #409eff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #66b1ff;
}
/* 配置视图过渡效果 */
::view-transition-new(root),
::view-transition-old(root) {
width: 100vw;
height: auto;
animation: none;
}
html.dark::view-transition-old(root) {
z-index: 9999;
}
html.dark::view-transition-new(root) {
z-index: 1;
}
html::view-transition-old(root) {
z-index: 1;
}
html::view-transition-new(root) {
z-index: 9999;
}
</style>
</head>
<body>
<button onclick="toggleTheme(event)">切换主题</button>
<script>
const buttonNode = document.querySelector("button");
let isDark = false;
function changeStyle() {
isDark = !isDark;
document.documentElement.classList.toggle("dark");
}
function toggleTheme(event) {
// 检查浏览器是否支持 startViewTransition
if (!document.startViewTransition) {
changeStyle();
return;
}
// 创建视图过渡
const transition = document.startViewTransition(() => changeStyle());
// 当过渡准备就绪时,设置动画效果
transition.ready.then(() => {
// 获取点击位置的坐标
const { clientX: x, clientY: y } = event;
// 计算覆盖整个页面所需的最大半径
const r = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y));
// 定义裁剪路径动画的两个状态
const clipPath = [
`circle(${r}px at ${x}px ${y}px)`,
`circle(0px at ${x}px ${y}px)`,
];
// 应用动画
document.documentElement.animate(
{
clipPath: isDark ? clipPath : clipPath.reverse(),
},
{
duration: 500,
easing: "ease-out",
// 根据主题切换方向选择动画目标
pseudoElement: isDark
? "::view-transition-old(root)"
: "::view-transition-new(root)",
}
);
});
}
</script>
</body>
</html>
2024/3/21大约 6 分钟