暗黑模式介绍

  • Hugo的even主题在github已经两年没有更新了,我应该是第一个为该主题提供暗黑模式的人(但是由于在手机端还有bug,我暂时还不想发起pull request,不过大家可以随便的copy我的代码并做出改进发起PR😄。

  • 2023.4.10更新: 添加了移动端的暗黑模式显示,见commit: update mobile dark mode,这意味着暗黑模式的全部bug已经得到解决,有时间我打算向even发起PR(虽然似乎even的作者失踪了)。

  • 最近试了很多方法,终于简单的在浏览器端实现了dark mode(点击右上角导航栏里的图标即可)。

    image

零前端基础具体代码实现 (Copy!)

作为一个只会matlabcpp语言的通信人,在零css,js等计算机前端基础下,我是怎么实现的呢?答案很简单,就是不断的copy代码,像写latex一样地写网页。

首先,我们注意到chrome浏览器中有一个很好用的插件, 这意味着我们只要copy这个插件的源码就可以了。所以我实现的代码流程如下(具体间commit: Add Dark Theme feature.):

  1. 为even主题/themes/even/layouts/partials/head.html添加fontawsomecss代码(之前有试过官网推荐的引用js代码的方式,虽然也可行,但是加载太慢,不推荐):
1
<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">

上述方法使用font-awsome的CDN,如果CDN挂了就g了,所以我将font-awsome部署到了本地:

  • 官方教程之下下载font-awesome-4.7.0文件夹,将其放置于/themes/even/static/css/之下,在head.html添加如下代码:

    1
    
    <link rel="stylesheet" href = "/css/font-awesome-4.7.0/css/font-awesome.css"></link>
    
  1. 安装dark mode,在本机C:\Users\RZY\AppData\Local\Google\Chrome\User Data\Default\Extensions\dmghijelimhndkbmpgbldicpogfkceaj\0.4.6_0\data\content_script\general处选择自己喜欢的dark.css,拷贝到/themes/even/static/css/下,并在/themes/even/layouts/partials/head.html下添加以下代码:
1
<link disabled id="dark-mode-theme" rel="stylesheet" href="/css/dark.css"></link>
  1. /themes/even/layouts/partials/header.htmlmenu中添加切换暗黑模式的图标:
1
2
3
4
5
<li class="menu-item">
    <a id="dark-mode-toggle" class="menu-item-link">
      <i id="dark-mode-toggle-i" class="fa fa-moon-o"></i>
    </a>
</li>
  1. /themes/even/layouts/partials/scripts.html添加以下js代码(网上copy的代码1),
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<script>
  //通过时间判断夜间模式,否则会完全手动切换并本地持久化模式,下次自动渲染本地持久化的模式
var darkMode = {
  config:{    
    startHour:19,//19点开始
    endHour:7,//7点结束    
  },
  _darkTheme:null,  //dark.css标签
  _modeToggle:null, //手动切换按钮块
  _modeToggleParent:null, //手动切换按钮wrap
  _currentHour:0, //当前小时
  _storageKey:"dark-mode-storage",
  _storageByHandLastTIme:0, //上次手动设置模式时间 毫秒
  _storageOverdueHours:12,  //每隔12小时重新检查本地持久化

  init:function(){
    //夜间模式切换配置
    this._modeToggleParent = document.getElementById("dark-mode-toggle");
    this._modeToggle = document.getElementById("dark-mode-toggle-i");    
    this._darkTheme = document.getElementById("dark-mode-theme");  
    this._currentHour = new Date().getHours();  

    this.toggleListen();
    this.initMode();
  },
  initMode:function(){
    //初始化模式,来源本地持久化或自动检测模式    
    let initMode = this.getModeFromStorage() || this.autoMode(); 
    this.setMode(initMode);
  },
  toggleListen:function(){
    let _this = this;
    //手动切换触发模式更改
    this._modeToggleParent.addEventListener("click", () => {
        if (this._modeToggle.className === "fa fa-moon-o") {
            _this.setModeByHand("dark");
        } else if (this._modeToggle.className === "fa fa-sun-o") {
            _this.setModeByHand("light");
        }
    });

  },  
  autoMode:function(){
    let _currentHour = this._currentHour;
    if(_currentHour > this.config.startHour || _currentHour < this.config.endHour){
      return "dark";  
    }  
    return "light";    
  },
  setMode:function(mode){
    if (mode === "dark") {
        this._darkTheme.disabled = false;
        this._modeToggle.className = "fa fa-sun-o";
    } else if (mode === "light") {
        this._darkTheme.disabled = true;
        this._modeToggle.className = "fa fa-moon-o";
    }          
  },
  setModeByHand:function(mode){
    this.setMode(mode);
    this.setModeToStorage(mode);    
  },
  setModeToStorage:function(mode){
    localStorage.setItem(this._storageKey, mode);
    localStorage.setItem(this._storageKey+"-last-time", (new Date().getTime()));     
  },
  getModeFromStorage:function(){
    let _mode = localStorage.getItem(this._storageKey);
    let _lastSetTime = localStorage.getItem(this._storageKey+"-last-time");
    if(_mode && _lastSetTime){
      _lastSetTime = _lastSetTime/1000;
      let _currentTime = new Date().getTime()/1000;
      let _overdueSeconds = this._storageOverdueHours * 3600;
      if(_currentTime - _lastSetTime < _overdueSeconds){            
        return _mode;
      }
    }
    localStorage.removeItem(this._storageKey);
    localStorage.removeItem(this._storageKey+"-last-time");
    return false;

  },
};
darkMode.init();
</script>