实现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>
相关推荐
前端Hardy9 分钟前
HTML&CSS:惊艳!科技感爆棚的登录页面代码解析
前端·javascript·html
我是哈哈hh21 分钟前
【AJAX项目】黑马头条——数据管理平台
前端·javascript·ajax·前端框架·axios·proxy模式
高端章鱼哥23 分钟前
分享一个 MySQL binlog 分析小工具
前端
Ronin-Lotus25 分钟前
上位机知识篇---AJAX
前端·javascript·ajax
Rika28 分钟前
手写mini-vue之后,我写了一份面试通关手册
前端·vue.js
Sherry00729 分钟前
CSS Grid 交互式指南(译)(下)
css·面试
我想说一句30 分钟前
使用React开发拉布布旅游智能聊天机器人的实践
前端·前端框架
wwy_frontend30 分钟前
积累:04-VUE2
前端
拾光拾趣录30 分钟前
箭头函数 vs 普通函数:从“this 指向混乱”到写出真正健壮的代码
前端·javascript
一只毛驴32 分钟前
浏览器中的事件冒泡,事件捕获,事件委托
前端·面试