实现elementplus官网主题切换特效

概述

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

实现效果

咱也实现一个差不多的

实现

ViewTransition API

实现上面的效果,先介绍下,ViewTransition,View Transitions APIViewTransition 接口表示视图过渡,并提供了在过渡到达不同状态时运行代码的功能(例如,准备运行动画,或动画完成),或跳过视图过渡。(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>
相关推荐
不会敲代码18 分钟前
前端组件化样式隔离实战:React CSS Modules、styled-components 与 Vue scoped 对比
css·vue.js·react.js
Angelial10 分钟前
Vue3 嵌套路由 KeepAlive:动态缓存与反向配置方案
前端·vue.js
jiayu37 分钟前
Angular学习笔记24:Angular 响应式表单 FormArray 与 FormGroup 相互嵌套
前端
jiayu38 分钟前
Angular6学习笔记13:HTTP(3)
前端
小码哥_常41 分钟前
Kotlin抽象类与接口:相爱相杀的编程“CP”
前端
evelynlab42 分钟前
Tapable学习
前端
LeeYaMaster1 小时前
15个例子熟练异步框架 Zone.js
前端·angular.js
evelynlab1 小时前
打包原理
前端
拳打南山敬老院2 小时前
Context 不是压缩出来的,而是设计出来的
前端·后端·aigc
用户3076752811272 小时前
💡 从"傻等"到"流淌":我在AI项目中实现流式输出的血泪史(附真实代码+深度解析)
前端