目录

昨天小朋友发烧了,跟了个后半夜,基本通宵的节奏,周六补了个下午,睡醒后虽然很精神,毕竟白天睡太久,到晚上看屏幕有点刺眼,想着www.9ong.com也开启个夜间模式,自己在看的时候,也舒服些。

想着应该就是一段简单的js和css,百度copy下代码放进去就可以了,但百度、google下,没有找到比较简洁优雅的方案,虽然思路方案大体一致,但觉得不够纯粹,自己在其他参考及hugo的基础上,结合自己的主题完成一个不错的demo。

想法

  • 夜间模式样式
  • 支持手动切换夜间与日间模式
  • 初始化夜间模式,通过时间自动检测
  • 初始化夜间模式,通过localstorage本地持久化获取

夜间模式样式

新增static/css/dark.css

html {
    background-color: #171717 !important;
}
html {
    filter: invert(100%) hue-rotate(180deg) brightness(105%) contrast(85%);
    -webkit-filter: invert(100%) hue-rotate(180deg) brightness(105%) contrast(85%);
}
body {
    background-color: #FFF !important;
}
img,
video,
body * [style*="background-image"] {
    filter: hue-rotate(180deg) contrast(100%) invert(100%);
    -webkit-filter: hue-rotate(180deg) contrast(100%) invert(100%);
}

由于我们在后面的js中使用到动态修改这个link标签的disabled值,所以我们破坏性的将link插入到了主题文件中的layouts\partials\script.html:

<!--夜间模式样式,来源谷歌浏览器插件-->
<link disabled id="dark-mode-theme" rel="stylesheet" href="/css/dark.css"></link>

可以根据自己的实际情况,看是要通过link来换肤,还是通过js中动态修改以上dark.css中的样式。找到自己舒适的操作,本文这个方式属于对主题文件的破坏性修改了,但目前对于我们自己的主题来说script.html就是用于加全局动态功能的文件,尽量不去改动其他布局html文件。

夜间模式手动切换按钮

<!--夜间模式手动切换-->
<li class="post-action" style="position: fixed;bottom: 20%;right: 4%;">
<a id="dark-mode-toggle" class="post-action-btn btn btn--default">
    <i id="dark-mode-toggle-i" class="fa fa-moon-o"></i>
</a>          
</li>      

直接追加到script.html文件中,也是全局的一个按钮。

夜间模式js代码

直接追加到script.html文件中,在按钮有了之后执行。

//通过时间判断夜间模式,否则会完全手动切换并本地持久化模式,下次自动渲染本地持久化的模式
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();

效果

点击www.9ong.com右下日间与夜间模式切换按钮。

参考

Adding dark mode to a Hugo static website without learning CSS