vue 实现Element Plus的炫酷主题切换

效果图

.vue

bash 复制代码
<template>
  <view class="flex-end">
    <div class="wxy-switch" :class="{'wxy-switch-checked':showView}"
    @click="themeSwitch" >
      <div class="wxy-switch-round"></div>
    </div>
  </view>
</template>

<script setup>
import {ref } from 'vue'

const showView = ref(false)

const themeSwitch = (e) => {
  showView.value = !showView.value;
  // 如果不支持 startViewTransition 直接切换
  if (!document.startViewTransition) {
  	document.documentElement.classList.toggle("dark");
  	return
  }

  const transition =  document.startViewTransition(() => {
    document.documentElement.classList.toggle("dark");
  });

  transition.ready.then(() => {
    const { clientX, clientY } = e
    const radius = Math.hypot(
      Math.max(clientX, window.innerWidth - clientX),
      Math.max(clientY, window.innerHeight - clientY)
    )
    
    const isDark = document.documentElement.classList.contains("dark");
    const clipPath = [
      `circle(0px at ${clientX}px ${clientY}px)`,
      `circle(${radius}px at ${clientX}px ${clientY}px)`,
    ]
    document.documentElement.animate(
      { clipPath: isDark ? clipPath.reverse() : clipPath },
      { 
        duration: 500,
        fill: "both",
        pseudoElement: isDark ? "::view-transition-old(root)" : "::view-transition-new(root)"
      }
    )
  });
}
</script>

<style scoped>
.flex-end{
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

.wxy-switch{
  --w:40px;
  --h:20px;

  position: relative;
  width: var(--w);
  height: var(--h);
  background-color: #D6D6D6;
  border-radius: 25px;
  transition: background-color 0.3s;
}

.wxy-switch-checked{
  background-color: #39b54a;
}

.wxy-switch-round{
  position: absolute;
  top: 0;
  bottom: 0;
  left: 1.5px;
  width: calc(var(--h) - 3px);
  height: calc(var(--h) - 3px);
  margin: auto 0;
  background: #fff;
  border-radius: 50%;
  transition: left 0.3s;
}

.wxy-switch-checked .wxy-switch-round{
  left: calc(100% - var(--h) + 1.5px);
}
</style>

.css

bash 复制代码
body{
  margin: 0;
}

:root {
  --theme-bg-color: #fff;
  --theme-text-color: #333;
}

:root.dark {
  --theme-bg-color: #333;
  --theme-text-color: #fff;
}

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

.dark::view-transition-old(root) {
  z-index: 9999;
}

#app {
  min-height: 100vh;
  background-color: var(--theme-bg-color);
  color: var(--theme-text-color);
  text-align: center;
  padding: 2rem;
}

div,a{
  box-sizing: border-box;
}

遇到问题可以看我主页加我,很少看博客,对你有帮助别忘记点赞收藏。

相关推荐
鹏多多44 分钟前
PC 网站接入微信登录,这 10 个坑我替你踩完了!
前端·javascript·vue.js
用户298698530142 小时前
React 中 HTML 内容转 Word 文档的实现方案
javascript·react.js·html
mONESY2 小时前
我用 Next.js 16 + Supabase 从零做了个「背单词」H5 应用
javascript
boooooooom2 小时前
手把手做一个图 RAG 烹饪问答系统:Neo4j + Milvus + LLM 的工程实践
前端·javascript·后端
染指11105 小时前
103.RAG-LLamaIndex后端rag问答-聊天接口
前端·javascript·vue.js·人工智能
单线程_0113 小时前
从案例分析 Vue3 Tokenizer+Parser 源码三
前端·javascript·vue.js
jay神14 小时前
【计算机毕业设计】基于SpringBoot的程序教学辅助系统
java·前端·vue.js·spring boot·后端·毕业设计·课程设计
小磊哥er15 小时前
深入解构Claude Code - 第 8 篇 · 数据放哪、钱怎么算
javascript·ai编程
kyriewen16 小时前
我装了30多个Skill,给AI安排了8个岗位
前端·javascript·ai编程
默_笙18 小时前
🔥 让 AI 帮我写完整个 Next.js 博客:框架就是 AI 的"上下文 buff"
前端·javascript