使用vue3实现element-plus的主题切换效果

 更新时间:2024年12月02日 10:39:29   作者:szx的开发笔记  
Vue3 Element Plus是一个基于Vue 3框架的UI组件库,它是由Element UI团队开发的升级版本,Element Plus延续了Element UI简洁、高效的风格,并引入了一些新的设计语言和技术,如响应式API和更好的性能优化,本文给大家介绍了如何使用vue3实现element-plus的主题切换效果

先看实现效果

实现过程

前提需要引入好 element-plus,并导入element的黑色主题CSS

示例,再 main.js 中引入

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import 'element-plus/theme-chalk/dark/css-vars.css' // 黑色主题

app.use(ElementPlus, {
  locale: locale,
  size: Cookies.get('size') || 'default'
})

接着编写下面的基础代码

<template>
  <div>
    <el-switch v-model='value1' class='switch' @change='changeSwitch'>
      <template #active-action>
        <el-icon>
          <Moon />
        </el-icon>
      </template>
      <template #inactive-action>
        <el-icon>
          <Sunny />
        </el-icon>
      </template>
    </el-switch>
  </div>
</template>

<script setup>
let value1 = ref(false)

function changeSwitch() {
  document.documentElement.classList.toggle('dark')
}
</script>
<style scoped lang='scss'>
.switch {
  position: absolute;
  left: 200px;
  top: 200px;
}
</style>

现在当切换 switch 时,背景颜色会直接进行黑白切换

从动画可以看到,现在是没有任何过渡效果的

我们可以使用 document.startViewTransition 很简单的就可以加上过渡效果,document.startViewTransition 接收一个函数参数,再函数内部写上操作DOM的逻辑代码即可实现一个默认的过度效果

function changeSwitch() {
  document.startViewTransition(() => {
    document.documentElement.classList.toggle('dark')
  })
}

现在就有了一个默认的过渡效果

为什么使用了 document.startViewTransition 就会有一个动画效果呢

MDN文档:Document:startViewTransition() 方法 - Web API | MDN

通过调用 API,让浏览器为新旧两种不同视图分别捕获并建立了快照 (即 ::view-transition-old(root)旧快照 和 ::view-transition-new(root) 新快照),而后新旧两快照在 ::view-transition-image-pair(root) 容器中完成转场动画的过渡。动画结束后则删除其相关伪元素 (快照和容器)。

我们也可以控制默认的动画时长

::view-transition-old(root), /* 旧视图*/
::view-transition-new(root) { /* 新视图*/
  animation-duration: 2s;
}

了解了这些,现在想点击按钮,实现一个扩散圆来实现主题切换效果,只需要根据按钮位置,计算圆的半径,然后设置 ::view-transition-new(root) 这个伪元素的动画效果,让圆从 0% 到 100%即可

完整代码

<template>
  <div>
    <el-switch v-model='isDark' class='switch' ref='switchRef' @change='changeSwitch'>
      <template #active-action>
        <el-icon>
          <Moon />
        </el-icon>
      </template>
      <template #inactive-action>
        <el-icon>
          <Sunny />
        </el-icon>
      </template>
    </el-switch>
  </div>
</template>

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

let isDark = ref(false)
let switchRef = ref(null)


function changeSwitch() {
  // 创建一个视图过渡动画,用于在切换深色模式时优化用户体验
  const transition = document.startViewTransition(() => {
    // 切换HTML文档的dark类,以激活或停用深色模式
    document.documentElement.classList.toggle('dark')
  })

  // 当视图过渡动画准备就绪时执行以下代码
  transition.ready.then(() => {
    // 获取switch组件的DOM元素,用于计算过渡动画的起点
    const switchElement = switchRef.value?.$el
    // 计算switch组件中心点的坐标
    const rect = switchElement.getBoundingClientRect()
    const x = rect.left + rect.width / 2
    const y = rect.top + rect.height / 2
    // 计算过渡动画结束时的圆半径,确保覆盖整个视口
    const endRadius = Math.hypot(
      Math.max(x, innerWidth - x),
      Math.max(y, innerHeight - y),
    )
    // 创建clipPath数组,定义了过渡动画的起始和结束形状
    const clipPath = [
      `circle(0 at ${x}px ${y}px)`,
      `circle(${endRadius}px at ${x}px ${y}px)`,
    ]
    // 在HTML文档的根元素上启动一个动画,根据当前是否为深色模式来决定动画的方向
    document.documentElement.animate(
      {
        clipPath: isDark.value ? clipPath.reverse() : clipPath,
      },
      {
        duration: 400, // 动画持续时间
        pseudoElement: isDark.value
          ? '::view-transition-old(root)'
          : '::view-transition-new(root)', // 根据深色模式状态选择伪元素
      },
    )
  })
}
</script>

<style>
::view-transition-new(root),
::view-transition-old(root) {
  /* 关闭默认动画,否则影响自定义动画的执行 */
  animation: none !important;
}

/*黑暗模式下,让旧节点的层级变高,否则会导致动画出不来*/
.dark::view-transition-old(root) {
  z-index: 100;
}
</style>

<style scoped>
.switch {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}
</style>

circle 表示画一个圆形,更多图像可参考:clip-path - CSS:层叠样式表 | MDN

以上就是使用vue3实现element-plus的主题切换效果的详细内容,更多关于vue3 element-plus主题切换的资料请关注脚本之家其它相关文章!

相关文章

  • 在vue-cli脚手架中配置一个vue-router前端路由

    在vue-cli脚手架中配置一个vue-router前端路由

    这篇文章主要给大家介绍了在vue-cli脚手架中配置一个vue-router前端路由的相关资料,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面跟着小编一起来学习学习吧。
    2017-07-07
  • Vue2与Vue3中diff算法的区别及说明

    Vue2与Vue3中diff算法的区别及说明

    Vue3通过双端Diff算法、静态标记、动态追踪、Fragment支持、事件缓存和BlockTree等优化,显著提升了性能,特别是在处理大规模静态内容时
    2025-10-10
  • Vue2中无法监听数组和对象的某些变化问题

    Vue2中无法监听数组和对象的某些变化问题

    这篇文章主要介绍了Vue2中无法监听数组和对象的某些变化问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • Vue中的循环遍历与key值原理解读

    Vue中的循环遍历与key值原理解读

    这篇文章主要介绍了Vue中的循环遍历与key值原理,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • Vue组件实现评论区功能

    Vue组件实现评论区功能

    这篇文章主要为大家详细介绍了Vue组件实现评论区功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • uniapp多地区、多平台、多环境打包具体代码与配置说明

    uniapp多地区、多平台、多环境打包具体代码与配置说明

    在移动开发领域,跨平台解决方案一直是开发者追求的目标,Uniapp凭借其独特的架构设计,实现了iOS、Android、H5、微信小程序等8个平台的代码复用,这篇文章主要介绍了uniapp多地区、多平台、多环境打包具体代码与配置说明的相关资料,需要的朋友可以参考下
    2026-03-03
  • vue执行配置选项npm run serve的本质图文详解

    vue执行配置选项npm run serve的本质图文详解

    本地开发一般通过执行npm run serve命令来启动项目,那这行命令到底存在什么魔法?下面这篇文章主要给大家介绍了关于vue执行配置选项npm run serve的本质的相关资料,需要的朋友可以参考下
    2023-05-05
  • 使用Vue和Firebase实现后台数据存储的示例代码

    使用Vue和Firebase实现后台数据存储的示例代码

    在现代 web 应用开发中,前端和后端的无缝协作至关重要,借助 Firebase 等云计算解决方案,前端开发者可以轻松实现数据存储与实时更新,本文将为大家详细介绍如何利用 Vue 3 的 Composition API 和 Firebase 实现后台数据存储,需要的朋友可以参考下
    2024-10-10
  • Vue3通过ref操作Dom元素及hooks的使用方法

    Vue3通过ref操作Dom元素及hooks的使用方法

    这篇文章主要介绍了Vue3通过ref操作Dom元素及hooks的使用方法,需要的朋友可以参考下
    2023-01-01
  • 对vue.js中this.$emit的深入理解

    对vue.js中this.$emit的深入理解

    下面小编就为大家分享一篇对vue.js中this.$emit的深入理解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-02-02

最新评论