实现elementplus官网主题切换特效

概述

在使用elementplus文档的时候,如果留意的话,点击主题切换,会发现有一个鱼眼动画的奇幻,非常的炫酷如下:

实现效果

咱也实现一个差不多的

实现

ViewTransition API

实现上面的效果,先介绍下,ViewTransition,View Transitions API 的 ViewTransition 接口表示视图过渡,并提供了在过渡到达不同状态时运行代码的功能(例如,准备运行动画,或动画完成),或跳过视图过渡。(mdn解释),View Transitions API 简化了复杂动画的实现,无需手动处理位置计算或动画控制,适合页面级的场景切换和动画增强。

具体代码事先

主要涉及到我们需要通过api提供的接口去做动画处理。

js 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
        :root {
            --color: #fff;
            background-color: var(--color);
        }

        :root.dark {
            --color: #008c8c;
        }

        ::view-transition-new(root),
        ::view-transition-old(root) {
            animation: none;
        }

        .dark::view-transition-old(root) {
            z-index: 100;
        }
    </style>
</head>

<body>
    <button id="operate-btn">切换主题</button>
    <script>
        const operateBtn = document.getElementById('operate-btn');

        function toggleTheme() {
            document.documentElement.classList.toggle('dark');
        }
        function operateFn(e) {
            const transition = document.startViewTransition(() => {
                toggleTheme()
            });
            transition.ready.then(() => {
                const { clientX, clientY } = e;
                // 计算半径,以鼠标点击的位置为圆心,到四个角的距离中最大的那个作为半径
                const radius = Math.hypot(
                    Math.max(clientX, innerWidth - clientX),
                    Math.max(clientY, innerHeight - clientY)
                );
                const clipPath = [
                    `circle(0% at ${clientX}px ${clientY}px)`,
                    `circle(${radius}px at ${clientX}px ${clientY}px)`
                ];
                const isDark = document.documentElement.classList.contains('dark');

                const clipPathList = isDark ? clipPath.reverse() : clipPath
                document.documentElement.animate(
                    {
                        // 切换方向相反
                        clipPath: clipPathList
                    },
                    {
                        duration: 300,
                        // 如果要切换到暗色主题
                        pseudoElement: isDark
                            ? '::view-transition-old(root)'
                            : '::view-transition-new(root)'
                    }
                );
            });
        }
        operateBtn.addEventListener('click', operateFn);
    </script>
</body>

</html>
相关推荐
IT_陈寒3 小时前
Vue开发实战:从入门到精通
前端·人工智能·后端
znnnk3 小时前
2026 前端工程化新纪元:Rust 重塑工具链,AI Agent 接管流水线
前端·人工智能·rust
王大师王文峰4 小时前
HTML 入门到进阶:语义化标签、表单与多媒体一篇打通【语义化布局、表单校验、video/audio、Canvas、无障碍与 SEO】
前端·css·node.js·html·css3·jquery·html5
风骏时光牛马4 小时前
AI_Coding:智能代码创作助手
前端
剪刀石头布啊12 小时前
vue-react为何要虚拟dom
前端
剪刀石头布啊12 小时前
ahooks常用的一些库,我们使用一下
前端
剪刀石头布啊12 小时前
从git更新本地提交记录到更新已经推送到远端记录
前端
Flynt15 小时前
axios 被投毒半年后,我把 npm 的"安全防线"实测了一遍:最信任的 SHA512 是安慰剂
前端·npm·node.js
excel15 小时前
Base62 和 Base64 有什么区别?
前端
风骏时光牛马16 小时前
大模型底层架构与AI源码深度剖析
前端