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;
}

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

相关推荐
im_AMBER4 小时前
Leetcode 162 除了自身以外数组的乘积 | 接雨水
开发语言·javascript·数据结构·算法·leetcode
Komorebi_99994 小时前
前端开发|18 个高频易错知识点汇总(HTML+CSS+JS+Vue)面试 & 开发通用
javascript·css·html
账号已注销free5 小时前
Vue3 defineProps使用指南
vue.js
LIO5 小时前
Pinia 极简指南:Vue 3 官方状态管理库
前端·vue.js
Wenzar_5 小时前
# D3.js实战进阶:从基础图表到交互式数据仪表盘的全流程构建在现代前端开发中,**数据可视化已成为提升用户体验的核心能力之一
java·javascript·python·信息可视化·ux
菜鸟小码5 小时前
MapReduce 编程模型详解:Mapper、Reducer、Driver 三大核心组件
大数据·javascript·mapreduce
Ruihong6 小时前
手写 React 对比 VuReact 编译:真正省下来的是维护成本
vue.js·react.js·面试
林恒smileZAZ6 小时前
CSS 滚动驱动动画(scroll-timeline):无 JS 实现滚动特效
前端·javascript·css
俺不会敲代码啊啊啊6 小时前
el-table实现行拖拽(包含展开项)
前端·vue.js·typescript
架构源启6 小时前
2026 进阶篇:Spring Boot响应式编程 + Spring AI 1.1.4 流式实战 + Vue前端完整实现(避坑指南)
java·前端·vue.js·人工智能·spring boot·spring·ai编程