likes
comments
collection
share

前端实现夜间模式

作者站长头像
站长
· 阅读数 13

最近写代码,项目要做暗色模式,就去阅读了公司的其他项目的前端代码如何实现此功能。简单做了一个demo,代码链接为 gitee,效果如下:

前端实现夜间模式

方法一

很多项目对于颜色都会声明为全局变量以便复用,比如声明:root下面

前端实现夜间模式

需要的话,直接通过var()引入即可

前端实现夜间模式

(对:rootvar不了解的小伙伴可以点击 :rootvar()

所以我们就可以声明两套颜色方案,使用的时候直接使用变量名,如下:

前端实现夜间模式

编辑完了颜色列表之后,下一步就是要判断白天或者黑夜,这里看个人需求,如果是web网站的话,一般都是提供一个按钮,手动切换;如果是客户端的web的话,一般都是通过url传参或者navigator.userAgent来获取相关值,这里提供下客户端的思路:

function isDark() {
  // 模式判断
  let theme

  // user-agent传参确定模式
  let userAgent = navigator.userAgent
  theme = userAgent.includes('Theme/Night') ? 'dark' : 'light'

  // 路径传参确定模式
  const url = new URL(location.href)
  const regex = /[?|&]mode=night/g
  if (regex.test(url.href)) {
    theme = 'dark'
  }

  return theme === 'dark'
}

web的话可以在 这里 尝试手动添加或者删除class来切换模式

实现了判断方法之后,最后一步就是把夜间的class添加到html上面

document.querySelector('html')?.classList.toggle('night-theme')

方法二

如果其他项目也要用到这些的话,可以考虑单独写一个js或者ts文件,部署之后,其他项目直接通过script标签引入,那里需要就直接添加相关类名

interface ColorList {
  color: string
  darkColor: string
  className: string
}

function isDark() {
  // 主题判断
  let theme

  // user-agent传参确定主题
  let userAgent = navigator.userAgent
  theme = userAgent.includes('Theme/Night') ? 'dark' : 'light'


  // 路径传参确定主题
  const url = new URL(location.href)
  const regex = /[?|&]mode=night/g
  
  if (regex.test(url.href)) {
    theme = 'dark'
  }

  return theme === 'dark'
}


function addStyle(lists: ColorList[], cssName: string, isDark: boolean) {
  let style = ''

  lists.forEach((value) => {
     let color = isDark ? value.darkColor : value.color
     style += `.${value.className} {${cssName}: ${color}}`
  })

  return style
}

export function addColor() {
   const bgColorList: ColorList[] = [{
     color: '#f7f7f7',
     darkColor: '#1d1e1e',
     className: 'mm-bg-color-1'},
   {
     color: '#ffffff',
     darkColor: '#272829',
     className: 'mm-bg-color-2'
  }]

   const borderColorList: ColorList[] = [{
     color: '#efefef',
     darkColor: '#4b4c4d',
     className: 'mm-bg-color-3'
     },{
     color: '#e5e5e5',
     darkColor: '#303030',
     className: 'mm-line-bg-color'
   }]

   const map = new Map().set('bgColorList', bgColorList).set('borderColorList', borderColorList)

   let colorList = ''
   map.forEach((value, key) => {
       if (key.includes('bgColorList')) {
          colorList += addStyle(value, 'background-color', true)
       }

      if (key.includes('borderColorList')) {
          colorList += addStyle(value, 'border-color', true)
      }

   })

  const styleElement = document.createElement('style')
  styleElement.innerText = colorList
  const html = document.querySelector('head')
  html?.append(styleElement)
}

整体思路是定义好白天和黑夜不同的颜色变量,设置className,建议map结构,遍历map获取数据,将样式整合到一起,最后创建style元素,添加到head标签里

前端实现夜间模式

这里我写的比较简单,就直接在main.ts里面执行了

前端实现夜间模式

结尾

如有错误,欢迎指正!