前言

Nuxt3 中要实现暗黑模式,需要用到一个库:color-mode,它可以帮助我们很轻易地实现暗黑模式切换。

具体使用

  1. 安装 @nuxtjs/color-mode 依赖:
pnpm add @nuxtjs/color-mode -D
  1. 打开 nuxt.config.ts 配置文件注入依赖:
export default defineNuxtConfig({
  modules: ['@nuxtjs/color-mode']
})
  1. 你也可以根据项目实际情况自定义配置,以下是一些默认配置:
import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({
  modules: ['@nuxtjs/color-mode'],
  colorMode: {
    preference: 'system', // default value of $colorMode.preference
    fallback: 'light', // fallback value if not system preference found
    hid: 'nuxt-color-mode-script',
    globalName: '__NUXT_COLOR_MODE__',
    componentName: 'ColorScheme',
    classPrefix: '',
    classSuffix: '-mode',
    storageKey: 'nuxt-color-mode'
  }
})

具体的使用文档:NuxtColorMode

按钮模式

  1. src/components 中新建 ColorMode/index.vue 文件:
 <script setup lang="ts">
 const colorMode = useColorMode()

 // 切换模式
 const setColorMode = () => {
   colorMode.value = colorMode.value === 'dark' ? 'light' : 'dark'
 }

 // 判断是否支持 startViewTransition API
 const enableTransitions = () =>
   'startViewTransition' in document &&
   window.matchMedia('(prefers-reduced-motion: no-preference)').matches

 // 切换动画
 async function toggleDark({ clientX: x, clientY: y }: MouseEvent) {
   const isDark = colorMode.value === 'dark'

   if (!enableTransitions()) {
     setColorMode()
     return
   }

   const clipPath = [
     `circle(0px at ${x}px ${y}px)`,
     `circle(${Math.hypot(
       Math.max(x, innerWidth - x),
       Math.max(y, innerHeight - y)
     )}px at ${x}px ${y}px)`
   ]

   await document.startViewTransition(async () => {
     setColorMode()
     await nextTick()
   }).ready

   document.documentElement.animate(
     { clipPath: !isDark ? clipPath.reverse() : clipPath },
     {
       duration: 300,
       easing: 'ease-in',
       pseudoElement: `::view-transition-${!isDark ? 'old' : 'new'}(root)`
     }
   )
 }
 </script>

 <template>
   <el-tooltip
     :content="`切换${$colorMode.value === 'dark' ? '白天' : '黑夜'}模式`"
     placement="bottom"
   >
     <el-button
       circle
       text
       @click="toggleDark"
     >
       <Icon
         :name="$colorMode.value === 'dark' ? 'i-heroicons-moon-solid' : 'i-heroicons-sun-solid'"
         class="h-5 w-5"
       />
     </el-button>
   </el-tooltip>
 </template>

 <style>
 ::view-transition-old(root),
 ::view-transition-new(root) {
   animation: none;
   mix-blend-mode: normal;
 }

 ::view-transition-old(root),
 .dark::view-transition-new(root) {
   z-index: 1;
 }

 ::view-transition-new(root),
 .dark::view-transition-old(root) {
   z-index: 9999;
 }
 </style>
  1. 在需要的地方加载组件:
<ColorMode />

最终效果

在这里插入图片描述

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部