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

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

相关推荐
Setsuna_F_Seiei18 分钟前
AI 对话应用之 JS 的流式接口数据处理
前端·javascript·ai编程
英俊潇洒美少年28 分钟前
react如何实现 vue的$nextTick的效果
javascript·vue.js·react.js
青柠代码录1 小时前
【Vue3】Vue Router 4 路由全解
前端·vue.js
蜡台2 小时前
element-ui 2 el-tree 内容超长滚动条不显示问题
前端·vue.js·elementui·el-tree·v-deep
daols883 小时前
vue甘特图 vxe-gantt 如何实现双击连接线自动删除线功能(含二次确认)
vue.js·甘特图·vxe-gantt
隔壁小邓4 小时前
前端Vue项目打包部署实战教程
前端·javascript·vue.js
TON_G-T4 小时前
javascript中 Iframe 处理多端通信、鉴权
开发语言·前端·javascript
周淳APP4 小时前
【JS之闭包防抖节流,this指向,原型&原型链,数据类型,深浅拷贝】简单梳理啦!
开发语言·前端·javascript·ecmascript
kyriewen5 小时前
console.log 骗了我一整个通宵:原来它才是时间旅行者
前端·javascript·chrome
冴羽5 小时前
在浏览器控制台调试的 6 个秘密技巧
前端·javascript·chrome