夜间模式动画

详见:博客魔改教程总结(一) | Fomalhaut🥝

  1. 新建[BlogRoot]\themes\butterfly\layout\includes\custom\sun_moon.pug,这部分其实实质上就是一个svg文件,通过js操作它的旋转显隐,淡入淡出实现动画效果。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    svg(aria-hidden='true', style='position:absolute; overflow:hidden; width:0; height:0')
    symbol#icon-sun(viewBox='0 0 1024 1024')
    path(d='M960 512l-128 128v192h-192l-128 128-128-128H192v-192l-128-128 128-128V192h192l128-128 128 128h192v192z', fill='#FFD878', p-id='8420')
    path(d='M736 512a224 224 0 1 0-448 0 224 224 0 1 0 448 0z', fill='#FFE4A9', p-id='8421')
    path(d='M512 109.248L626.752 224H800v173.248L914.752 512 800 626.752V800h-173.248L512 914.752 397.248 800H224v-173.248L109.248 512 224 397.248V224h173.248L512 109.248M512 64l-128 128H192v192l-128 128 128 128v192h192l128 128 128-128h192v-192l128-128-128-128V192h-192l-128-128z', fill='#4D5152', p-id='8422')
    path(d='M512 320c105.888 0 192 86.112 192 192s-86.112 192-192 192-192-86.112-192-192 86.112-192 192-192m0-32a224 224 0 1 0 0 448 224 224 0 0 0 0-448z', fill='#4D5152', p-id='8423')
    symbol#icon-moon(viewBox='0 0 1024 1024')
    path(d='M611.370667 167.082667a445.013333 445.013333 0 0 1-38.4 161.834666 477.824 477.824 0 0 1-244.736 244.394667 445.141333 445.141333 0 0 1-161.109334 38.058667 85.077333 85.077333 0 0 0-65.066666 135.722666A462.08 462.08 0 1 0 747.093333 102.058667a85.077333 85.077333 0 0 0-135.722666 65.024z', fill='#FFB531', p-id='11345')
    path(d='M329.728 274.133333l35.157333-35.157333a21.333333 21.333333 0 1 0-30.165333-30.165333l-35.157333 35.157333-35.114667-35.157333a21.333333 21.333333 0 0 0-30.165333 30.165333l35.114666 35.157333-35.114666 35.157334a21.333333 21.333333 0 1 0 30.165333 30.165333l35.114667-35.157333 35.157333 35.157333a21.333333 21.333333 0 1 0 30.165333-30.165333z', fill='#030835', p-id='11346')
  2. 新建[BlogRoot]\themes\butterfly\source\css\_layout\sun_moon.styl

    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
    .Cuteen_DarkSky,
    .Cuteen_DarkSky:before
    content ''
    position fixed
    left 0
    right 0
    top 0
    bottom 0
    z-index 88888888

    .Cuteen_DarkSky
    background linear-gradient(#feb8b0, #fef9db)
    &:before
    transition 2s ease all
    opacity 0
    background linear-gradient(#4c3f6d, #6c62bb, #93b1ed)

    .DarkMode
    .Cuteen_DarkSky
    &:before
    opacity 1

    .Cuteen_DarkPlanet
    z-index 99999999
    position fixed
    left -50%
    top -50%
    width 200%
    height 200%
    -webkit-animation CuteenPlanetMove 2s cubic-bezier(0.7, 0, 0, 1)
    animation CuteenPlanetMove 2s cubic-bezier(0.7, 0, 0, 1)
    transform-origin center bottom


    @-webkit-keyframes CuteenPlanetMove {
    0% {
    transform: rotate(0);
    }
    to {
    transform: rotate(360deg);
    }
    }
    @keyframes CuteenPlanetMove {
    0% {
    transform: rotate(0);
    }
    to {
    transform: rotate(360deg);
    }
    }
    .Cuteen_DarkPlanet
    &:after
    position absolute
    left 35%
    top 40%
    width 9.375rem
    height 9.375rem
    border-radius 50%
    content ''
    background linear-gradient(#fefefe, #fffbe8)

    .search
    span
    display none

    .menus_item
    a
    text-decoration none!important
    //按钮相关,对侧栏按钮做过魔改的可以调整这里的数值
    .icon-V
    padding 5px
  3. 新建[BlogRoot]\themes\butterfly\source\js\sun_moon.js,去除了冗余代码,去jquery

    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
    function switchNightMode() {
    document.querySelector('body').insertAdjacentHTML('beforeend', '<div class="Cuteen_DarkSky"><div class="Cuteen_DarkPlanet"></div></div>'),
    setTimeout(function() {
    document.querySelector('body').classList.contains('DarkMode') ? (document.querySelector('body').classList.remove('DarkMode'), localStorage.setItem('isDark', '0'), document.getElementById('modeicon').setAttribute('xlink:href', '#icon-moon')) : (document.querySelector('body').classList.add('DarkMode'), localStorage.setItem('isDark', '1'), document.getElementById('modeicon').setAttribute('xlink:href', '#icon-sun')),
    setTimeout(function() {
    document.getElementsByClassName('Cuteen_DarkSky')[0].style.transition = 'opacity 3s';
    document.getElementsByClassName('Cuteen_DarkSky')[0].style.opacity = '0';
    setTimeout(function() {
    document.getElementsByClassName('Cuteen_DarkSky')[0].remove();
    }, 1e3);
    }, 2e3)
    })
    const nowMode = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light'
    if (nowMode === 'light') {
    activateDarkMode()
    saveToLocal.set('theme', 'dark', 2)
    GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.day_to_night)
    document.getElementById('modeicon').setAttribute('xlink:href', '#icon-sun')
    } else {
    activateLightMode()
    saveToLocal.set('theme', 'light', 2)
    document.querySelector('body').classList.add('DarkMode'), document.getElementById('modeicon').setAttribute('xlink:href', '#icon-moon')
    }
    // handle some cases
    typeof utterancesTheme === 'function' && utterancesTheme()
    typeof FB === 'object' && window.loadFBComment()
    window.DISQUS && document.getElementById('disqus_thread').children.length && setTimeout(() => window.disqusReset(), 200)
    }
  4. 修改[BlogRoot]\themes\butterfly\layout\includes\head.pug,在文件末位加上一行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    DIFF
    //- global config
    !=partial('includes/head/config', {}, {cache: true})

    include ./head/config_site.pug
    include ./head/noscript.pug

    !=fragment_cache('injectHeadJs', function(){return inject_head_js()})

    !=fragment_cache('injectHead', function(){return injectHtml(theme.inject.head)})
    + include ./custom/sun_moon.pug
  5. 修改[BlogRoot]\themes\butterfly\layout\includes\rightside.pug,把原本的昼夜切换按钮替换掉

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      when 'translate'
    if translate.enable
    button#translateLink(type="button" title=_p('rightside.translate_title'))= translate.default
    when 'darkmode'
    if darkmode.enable && darkmode.button
    - button#darkmode(type="button" title=_p('rightside.night_mode_title'))
    - i.fas.fa-adjust
    + a.icon-V.hidden(onclick='switchNightMode()', title=_p('rightside.night_mode_title'))
    + svg(width='25', height='25', viewBox='0 0 1024 1024')
    + use#modeicon(xlink:href='#icon-moon')
  6. 修改[BlogRoot]\_config.butterfly.yml,引入一下js

    1
    2
    3
    inject:
    bottom:
    + - <script src="/js/sun_moon.js" async></script>
  7. 重启项目并切换夜间模式即可看见效果

    1
    hexo cl; hexo s

夜间模式切换动画升级

逛博客看见别人的切换动画有月亮,而且颜色也很好看,于是一顿f12操作下大概看懂原理,再结合现在的动画改进一下就是了。(注意:在做本魔改前,请先完成店长的夜间模式切换动画,同时最好也要有引入Vue+Element弹窗。本动画是基于店长的样式改进的,加入了弯月,切换到夜间模式是太阳变月亮,切换到白天模式是月亮变太阳,同时背景颜色也改为了我喜欢的。)

效果预览

  1. 替换原来的[BlogRoot]\source\js\sun_moon.js为以下代码,这里主要改进是由原来的after遮罩换为两个元素,再通过定时器来控制各自元素的透明度达到绘制太阳和月亮的目的:

    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
    function switchNightMode() {
    document.querySelector('body').insertAdjacentHTML('beforeend', '<div class="Cuteen_DarkSky"><div class="Cuteen_DarkPlanet"><div id="sun"></div><div id="moon"></div></div></div>'),
    setTimeout(function () {
    document.querySelector('body').classList.contains('DarkMode') ? (document.querySelector('body').classList.remove('DarkMode'), localStorage.setItem('isDark', '0'), document.getElementById('modeicon').setAttribute('xlink:href', '#icon-moon')) : (document.querySelector('body').classList.add('DarkMode'), localStorage.setItem('isDark', '1'), document.getElementById('modeicon').setAttribute('xlink:href', '#icon-sun')),
    setTimeout(function () {
    document.getElementsByClassName('Cuteen_DarkSky')[0].style.transition = 'opacity 3s';
    document.getElementsByClassName('Cuteen_DarkSky')[0].style.opacity = '0';
    setTimeout(function () {
    document.getElementsByClassName('Cuteen_DarkSky')[0].remove();
    }, 1e3);
    }, 2e3)
    })
    const nowMode = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light'
    if (nowMode === 'light') {
    // 先设置太阳月亮透明度
    document.getElementById("sun").style.opacity = "1";
    document.getElementById("moon").style.opacity = "0";
    setTimeout(function () {
    document.getElementById("sun").style.opacity = "0";
    document.getElementById("moon").style.opacity = "1";
    }, 1000);

    activateDarkMode()
    saveToLocal.set('theme', 'dark', 2)
    // GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.day_to_night)
    document.getElementById('modeicon').setAttribute('xlink:href', '#icon-sun')
    // 延时弹窗提醒
    setTimeout(() => {
    new Vue({
    data: function () {
    this.$notify({
    title: "关灯啦🌙",
    message: "当前已成功切换至夜间模式!",
    position: 'top-left',
    offset: 50,
    showClose: true,
    type: "success",
    duration: 5000
    });
    }
    })
    }, 2000)
    } else {
    // 先设置太阳月亮透明度
    document.getElementById("sun").style.opacity = "0";
    document.getElementById("moon").style.opacity = "1";
    setTimeout(function () {
    document.getElementById("sun").style.opacity = "1";
    document.getElementById("moon").style.opacity = "0";
    }, 1000);

    activateLightMode()
    saveToLocal.set('theme', 'light', 2)
    document.querySelector('body').classList.add('DarkMode'), document.getElementById('modeicon').setAttribute('xlink:href', '#icon-moon')
    setTimeout(() => {
    new Vue({
    data: function () {
    this.$notify({
    title: "开灯啦🌞",
    message: "当前已成功切换至白天模式!",
    position: 'top-left',
    offset: 50,
    showClose: true,
    type: "success",
    duration: 5000
    });
    }
    })
    }, 2000)
    }
    // handle some cases
    typeof utterancesTheme === 'function' && utterancesTheme()
    typeof FB === 'object' && window.loadFBComment()
    window.DISQUS && document.getElementById('disqus_thread').children.length && setTimeout(() => window.disqusReset(), 200)
    }
  2. 替换原来的[BlogRoot]\themes\butterfly\source\css\_layout\sun_moon.styl为以下代码,主要改变是的绘制太阳和月亮的矢量信息,还有背景颜色改进:

    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
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    复制成功
    .Cuteen_DarkSky,
    .Cuteen_DarkSky:before
    content ''
    position fixed
    left 0
    right 0
    top 0
    bottom 0
    z-index 88888888

    .Cuteen_DarkSky
    background linear-gradient(to top, #f8cd71 0, #5bfde9 80%)
    &:before
    transition 2s ease all
    opacity 0
    background linear-gradient(to top, #30cfd0 0, #330867 100%)

    .DarkMode
    .Cuteen_DarkSky
    &:before
    opacity 1

    .Cuteen_DarkPlanet
    z-index 99999999
    position fixed
    left -50%
    top -50%
    width 200%
    height 200%
    -webkit-animation CuteenPlanetMove 2s cubic-bezier(0.7, 0, 0, 1)
    animation CuteenPlanetMove 2s cubic-bezier(0.7, 0, 0, 1)
    transform-origin center bottom


    @-webkit-keyframes CuteenPlanetMove {
    0% {
    transform: rotate(0);
    }
    to {
    transform: rotate(360deg);
    }
    }
    @keyframes CuteenPlanetMove {
    0% {
    transform: rotate(0);
    }
    to {
    transform: rotate(360deg);
    }
    }
    .Cuteen_DarkPlanet
    #sun
    position absolute
    border-radius 100%
    left 44%
    top 30%
    height 6rem
    width 6rem
    background #ffee94
    box-shadow 0 0 40px #ffee94
    // opacity 0

    #moon
    position absolute
    border-radius 100%
    left 44%
    top 30%
    position absolute
    border-radius 100%
    height 6rem
    width 6rem
    box-shadow -1.8em 1.8em 0 0.2em #fff
    // opacity 1

    // &:after
    // position absolute
    // left 42%
    // top 30%
    // width 6rem
    // height 6rem
    // border-radius 50%
    // content ''
    // background #ffef9e
    // box-shadow 0 0 30px #ffef9e

    .search
    span
    display none

    .menus_item
    a
    text-decoration none!important
    //按钮相关,对侧栏按钮做过魔改的可以调整这里的数值
    // .icon-V
    // padding 5px
  3. 重启项目并切换夜间模式即可看到效果:

    1
    hexo cl; hexo s

随机访问一篇文章

首先我们需要先下载baidusitemap插件
运行命令:npm install hexo-generator-baidu-sitemap --save
相信大部分人的hexo版本都在3以上,所以不需要在config.yml进行配置。

插件地址:https://www.npmjs.com/package/hexo-generator-baidu-sitemap

添加随机文章函数

然后在我们的自定义js文件中添加一个js函数
自定义js看这篇文章:Hexo博客添加自定义css和js文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 发现有时会和当前页面重复,加一个判断
function randomPost() {
fetch('/baidusitemap.xml').then(res => res.text()).then(str => (new window.DOMParser()).parseFromString(str, "text/xml")).then(data => {
let ls = data.querySelectorAll('url loc');
while (true) {
let url = ls[Math.floor(Math.random() * ls.length)].innerHTML;
if (location.href == url) continue;
location.href = url;
return;
}
})
}
// 阅读文章时看了一遍写的代码,发现加个数组和一个遍历完全没必要,改成下面这个即可。
// function randomPost() {
// fetch('/baidusitemap.xml').then(res => res.text()).then(str => (new window.DOMParser()).parseFromString(str, "text/xml")).then(data => {
// let ls = data.querySelectorAll('url loc');
// location.href = ls[Math.floor(Math.random() * ls.length)].innerHTML
// })
// }

添加导航栏按钮

魔改用户

添加好js之后,我们可以在右上角的按钮区添加一个按钮方便用户点击。

注意:此方法只适合魔改的用户,没魔改的使用可能会乱码。没有css基础谨慎添加。
没有魔改的用户可以继续往下看,我专门准备了另一个方法。(还是那么贴心)

打开themes\butterfly\layout\includes\header\nav.pug,在适当位置添加:

1
2
3
#randomPost
a.site-page.social-icon.search(href="javascript:;" onclick="randomPost()" title="随机访问一篇文章")
i.fas.fa-circle-notch.fa-fw

普通用户

没有魔改的用户可以在配置中添加一个导航按钮

1
2
menu:
随机访问: javascript:randomPost(); || fa-solid fa-shuffle

如果你只想显示图标不想显示文字的话,你可以这么写(图标后面会有一个小空格,不影响)

1
2
menu:
"": javascript:randomPost(); || fa-solid fa-shuffle

自定义右键菜单

右键菜单前置教程:昼夜切换动画、随机访问一篇文章,请完成这两个前置教程再来做这个,或者可以注释掉pug文件中对应的功能就不会出发相应不存在的函数了。

  1. 新建 [BlogRoot]\themes\butterfly\layout\includes\rightmenu.pug,编写以下内容:

    我这里统一采用font-Awesome的图标,因为颜色比较统一,就没用iconfont的图标了

    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
    #rightMenu.js-pjax
    .rightMenu-group.rightMenu-small
    a.rightMenu-item(href="javascript:window.history.back();")
    i.fa.fa-arrow-left
    a.rightMenu-item(href="javascript:window.history.forward();")
    i.fa.fa-arrow-right
    a.rightMenu-item(href="javascript:window.location.reload();")
    i.fa.fa-refresh
    a.rightMenu-item(href="javascript:rmf.scrollToTop();")
    i.fa.fa-arrow-up
    .rightMenu-group.rightMenu-line.hide#menu-text
    a.rightMenu-item(href="javascript:rmf.copySelect();")
    i.fa.fa-copy
    span='复制'
    a.rightMenu-item(href="javascript:window.open(\"https://www.baidu.com/s?wd=\"+window.getSelection().toString());window.location.reload();")
    i.fa.fa-search
    span='百度搜索'
    .rightMenu-group.rightMenu-line.hide#menu-too
    a.rightMenu-item(href="javascript:window.open(window.getSelection().toString());window.location.reload();")
    i.fa.fa-link
    span='转到链接'
    .rightMenu-group.rightMenu-line.hide#menu-paste
    a.rightMenu-item(href='javascript:rmf.paste()')
    i.fa.fa-copy
    span='粘贴'
    .rightMenu-group.rightMenu-line.hide#menu-post
    a.rightMenu-item(href="#post-comment")
    i.fas.fa-comment
    span='空降评论'
    a.rightMenu-item(href="javascript:rmf.copyWordsLink()")
    i.fa.fa-link
    span='复制本文地址'
    .rightMenu-group.rightMenu-line.hide#menu-to
    a.rightMenu-item(href="javascript:rmf.openWithNewTab()")
    i.fa.fa-window-restore
    span='新窗口打开'
    a.rightMenu-item#menu-too(href="javascript:rmf.open()")
    i.fa.fa-link
    span='转到链接'
    a.rightMenu-item(href="javascript:rmf.copyLink()")
    i.fa.fa-copy
    span='复制链接'
    .rightMenu-group.rightMenu-line.hide#menu-img
    a.rightMenu-item(href="javascript:rmf.saveAs()")
    i.fa.fa-download
    span='保存图片'
    a.rightMenu-item(href="javascript:rmf.openWithNewTab()")
    i.fa.fa-window-restore
    span='在新窗口打开'
    a.rightMenu-item(href="javascript:rmf.copyLink()")
    i.fa.fa-copy
    span='复制图片链接'
    .rightMenu-group.rightMenu-line
    a.rightMenu-item(href="javascript:randomPost()")
    i.fa.fa-paper-plane
    span='随便逛逛'
    a.rightMenu-item(href="javascript:switchNightMode();")
    i.fa.fa-moon
    span='昼夜切换'
    if is_post()||is_page()
    a.rightMenu-item(href="javascript:rmf.switchReadMode();")
    i.fa.fa-book
    span='阅读模式'
    a.rightMenu-item(href="/personal/about/")
    i.fa.fa-info-circle
    span='关于博客'
    a.rightMenu-item(href="javascript:toggleWinbox();")
    i.fas.fa-cog
    span='美化设置'
    a.rightMenu-item(href="javascript:rmf.fullScreen();")
    i.fas.fa-expand
    span='切换全屏'
    a.rightMenu-item(href="javascript:window.print();")
    i.fa-solid.fa-print
    span='打印页面'
  2. 然后在 [BlogRoot]/themes/butterfly/layout/includes/layout.pug中引入(注意缩进,去掉+)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    doctype html
    html(lang=config.language data-theme=theme.display_mode class=htmlClassHideAside)
    head
    include ./head.pug
    body
    ...

    else
    include ./404.pug

    include ./rightside.pug
    !=partial('includes/third-party/search/index', {}, {cache: true})
    + !=partial('includes/rightmenu',{}, {cache:true})
    include ./additional-js.pug
  3. 在自定义的custom.css中加入以下样式描述菜单,其中重要的颜色我都做了备注,根据自己的需要修改

    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
    /* 右键菜单 */
    #rightMenu {
    display: none;
    position: fixed;
    width: 160px;
    height: fit-content;
    top: 10%;
    left: 10%;
    /* 菜单面板背景色 */
    background-color: var(--card-bg);
    /* 菜单面板文字颜色 */
    border: 1px solid var(--font-color);
    border-radius: 8px;
    z-index: 100;
    }
    #rightMenu .rightMenu-group {
    padding: 7px 6px;
    }
    #rightMenu .rightMenu-group:not(:nth-last-child(1)) {
    border-bottom: 1px solid var(--font-color);
    }
    #rightMenu .rightMenu-group.rightMenu-small {
    display: flex;
    justify-content: space-between;
    }
    #rightMenu .rightMenu-group .rightMenu-item {
    height: 30px;
    line-height: 30px;
    border-radius: 8px;
    transition: 0.3s;
    color: var(--font-color);
    }
    #rightMenu .rightMenu-group.rightMenu-line .rightMenu-item {
    display: flex;
    height: 40px;
    line-height: 40px;
    padding: 0 4px;
    }
    #rightMenu .rightMenu-group .rightMenu-item:hover {
    /* 鼠标悬浮选项颜色 */
    background-color: var(--text-bg-hover);
    }
    #rightMenu .rightMenu-group .rightMenu-item i {
    display: inline-block;
    text-align: center;
    line-height: 30px;
    width: 30px;
    height: 30px;
    padding: 0 5px;
    }
    #rightMenu .rightMenu-group .rightMenu-item span {
    line-height: 30px;
    }

    #rightMenu .rightMenu-group.rightMenu-line .rightMenu-item * {
    height: 40px;
    line-height: 40px;
    }
    .rightMenu-group.hide {
    display: none;
    }
  4. 创建 [BlogRoot]/themes/butterfly/source/js/rightmenu.js,并写入如下代码:

    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
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    function setMask() {
    //设置遮罩
    if (document.getElementsByClassName("rmMask")[0] != undefined)
    return document.getElementsByClassName("rmMask")[0];
    mask = document.createElement('div');
    mask.className = "rmMask";
    mask.style.width = window.innerWidth + 'px';
    mask.style.height = window.innerHeight + 'px';
    mask.style.background = '#fff';
    mask.style.opacity = '.0';
    mask.style.position = 'fixed';
    mask.style.top = '0';
    mask.style.left = '0';
    mask.style.zIndex = 998;
    document.body.appendChild(mask);
    document.getElementById("rightMenu").style.zIndex = 19198;
    return mask;
    }

    function insertAtCursor(myField, myValue) {

    //IE 浏览器
    if (document.selection) {
    myField.focus();
    sel = document.selection.createRange();
    sel.text = myValue;
    sel.select();
    }

    //FireFox、Chrome等
    else if (myField.selectionStart || myField.selectionStart == '0') {
    var startPos = myField.selectionStart;
    var endPos = myField.selectionEnd;

    // 保存滚动条
    var restoreTop = myField.scrollTop;
    myField.value = myField.value.substring(0, startPos) + myValue + myField.value.substring(endPos, myField.value.length);

    if (restoreTop > 0) {
    myField.scrollTop = restoreTop;
    }

    myField.focus();
    myField.selectionStart = startPos + myValue.length;
    myField.selectionEnd = startPos + myValue.length;
    } else {
    myField.value += myValue;
    myField.focus();
    }
    }

    let rmf = {};
    rmf.showRightMenu = function (isTrue, x = 0, y = 0) {
    let $rightMenu = $('#rightMenu');
    $rightMenu.css('top', x + 'px').css('left', y + 'px');

    if (isTrue) {
    $rightMenu.show();
    } else {
    $rightMenu.hide();
    }
    }

    rmf.copyWordsLink = function () {
    let url = window.location.href
    let txa = document.createElement("textarea");
    txa.value = url;
    document.body.appendChild(txa)
    txa.select();
    document.execCommand("Copy");
    document.body.removeChild(txa);
    }
    rmf.switchReadMode = function () {
    const $body = document.body
    $body.classList.add('read-mode')
    const newEle = document.createElement('button')
    newEle.type = 'button'
    newEle.className = 'fas fa-sign-out-alt exit-readmode'
    $body.appendChild(newEle)

    function clickFn() {
    $body.classList.remove('read-mode')
    newEle.remove()
    newEle.removeEventListener('click', clickFn)
    }

    newEle.addEventListener('click', clickFn)
    }

    //复制选中文字
    rmf.copySelect = function () {
    document.execCommand('Copy', false, null);
    }

    //回到顶部
    rmf.scrollToTop = function () {
    document.getElementsByClassName("menus_items")[1].setAttribute("style", "");
    document.getElementById("name-container").setAttribute("style", "display:none");
    btf.scrollToDest(0, 500);
    }

    document.body.addEventListener('touchmove', function () {

    }, { passive: false });

    function popupMenu() {
    window.oncontextmenu = function (event) {
    // if (event.ctrlKey) return true;

    // 当关掉自定义右键时候直接返回
    if (mouseMode == "off") return true;

    $('.rightMenu-group.hide').hide();
    if (document.getSelection().toString()) {
    $('#menu-text').show();
    }
    if (document.getElementById('post')) {
    $('#menu-post').show();
    } else {
    if (document.getElementById('page')) {
    $('#menu-post').show();
    }
    }
    var el = window.document.body;
    el = event.target;
    var a = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\*\+,;=.]+$/
    if (a.test(window.getSelection().toString()) && el.tagName != "A") {
    $('#menu-too').show()
    }
    if (el.tagName == 'A') {
    $('#menu-to').show()
    rmf.open = function () {
    if (el.href.indexOf("http://") == -1 && el.href.indexOf("https://") == -1 || el.href.indexOf("yisous.xyz") != -1) {
    pjax.loadUrl(el.href)
    }
    else {
    location.href = el.href
    }
    }
    rmf.openWithNewTab = function () {
    window.open(el.href);
    // window.location.reload();
    }
    rmf.copyLink = function () {
    let url = el.href
    let txa = document.createElement("textarea");
    txa.value = url;
    document.body.appendChild(txa)
    txa.select();
    document.execCommand("Copy");
    document.body.removeChild(txa);
    }
    } else if (el.tagName == 'IMG') {
    $('#menu-img').show()
    rmf.openWithNewTab = function () {
    window.open(el.src);
    // window.location.reload();
    }
    rmf.click = function () {
    el.click()
    }
    rmf.copyLink = function () {
    let url = el.src
    let txa = document.createElement("textarea");
    txa.value = url;
    document.body.appendChild(txa)
    txa.select();
    document.execCommand("Copy");
    document.body.removeChild(txa);
    }
    rmf.saveAs = function () {
    var a = document.createElement('a');
    var url = el.src;
    var filename = url.split("/")[-1];
    a.href = url;
    a.download = filename;
    a.click();
    window.URL.revokeObjectURL(url);
    }
    } else if (el.tagName == "TEXTAREA" || el.tagName == "INPUT") {
    $('#menu-paste').show();
    rmf.paste = function () {
    navigator.permissions
    .query({
    name: 'clipboard-read'
    })
    .then(result => {
    if (result.state == 'granted' || result.state == 'prompt') {
    //读取剪贴板
    navigator.clipboard.readText().then(text => {
    console.log(text)
    insertAtCursor(el, text)
    })
    } else {
    Snackbar.show({
    text: '请允许读取剪贴板!',
    pos: 'top-center',
    showAction: false,
    })
    }
    })
    }
    }
    let pageX = event.clientX + 10;
    let pageY = event.clientY;
    let rmWidth = $('#rightMenu').width();
    let rmHeight = $('#rightMenu').height();
    if (pageX + rmWidth > window.innerWidth) {
    pageX -= rmWidth + 10;
    }
    if (pageY + rmHeight > window.innerHeight) {
    pageY -= pageY + rmHeight - window.innerHeight;
    }
    mask = setMask();
    // 滚动消失的代码和阅读进度有冲突,因此放到readPercent.js里面了
    $(".rightMenu-item").click(() => {
    $('.rmMask').attr('style', 'display: none');
    })
    $(window).resize(() => {
    rmf.showRightMenu(false);
    $('.rmMask').attr('style', 'display: none');
    })
    mask.onclick = () => {
    $('.rmMask').attr('style', 'display: none');
    }
    rmf.showRightMenu(true, pageY, pageX);
    $('.rmMask').attr('style', 'display: flex');
    return false;
    };

    window.addEventListener('click', function () {
    rmf.showRightMenu(false);
    });
    }
    if (!(navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
    popupMenu()
    }
    const box = document.documentElement

    function addLongtabListener(target, callback) {
    let timer = 0 // 初始化timer

    target.ontouchstart = () => {
    timer = 0 // 重置timer
    timer = setTimeout(() => {
    callback();
    timer = 0
    }, 380) // 超时器能成功执行,说明是长按
    }

    target.ontouchmove = () => {
    clearTimeout(timer) // 如果来到这里,说明是滑动
    timer = 0
    }

    target.ontouchend = () => { // 到这里如果timer有值,说明此触摸时间不足380ms,是点击
    if (timer) {
    clearTimeout(timer)
    }
    }
    }

    addLongtabListener(box, popupMenu)

    // 全屏
    rmf.fullScreen = function () {
    if (document.fullscreenElement) document.exitFullscreen();
    else document.documentElement.requestFullscreen();
    }

    // 右键开关
    if (localStorage.getItem("mouse") == undefined) {
    localStorage.setItem("mouse", "on");
    }
    var mouseMode = localStorage.getItem("mouse");
    function changeMouseMode() {
    if (localStorage.getItem("mouse") == "on") {
    mouseMode = "off";
    localStorage.setItem("mouse", "off");
    debounce(function () {
    new Vue({
    data: function () {
    this.$notify({
    title: "切换右键模式成功🍔",
    message: "当前鼠标右键已恢复为系统默认!",
    position: 'top-left',
    offset: 50,
    showClose: true,
    type: "success",
    duration: 5000
    });
    }
    })
    }, 300);
    } else {
    mouseMode = "on";
    localStorage.setItem("mouse", "on");
    debounce(function () {
    new Vue({
    data: function () {
    this.$notify({
    title: "切换右键模式成功🍔",
    message: "当前鼠标右键已更换为网站指定样式!",
    position: 'top-left',
    offset: 50,
    showClose: true,
    type: "success",
    duration: 5000
    });
    }
    })
    }, 300);
    }
    }
  5. 引入jQuery依赖以及上述的css和js文件(custom.css默认已经引入了就不重复引用了)

    1
    2
    3
    4
    inject:
    bottom:
    + - <script type="text/javascript" src="https://cdn1.tianli0.top/npm/jquery@latest/dist/jquery.min.js"></script>
    + - <script type="text/javascript" src="/js/rightmenu.js"></script>
  6. 本来到这里重启项目就可以见效了,我这里还加了一个右键开关,取消了原来ctrl复合的右键开关策略。因此还需要加一个右键开关的按钮,在[BlogRoot]\themes\butterfly\layout\includes\rightside.pug中做如下的修改,目的就是把鼠标开关放到右边栏的设置隐藏项里面,这样我们就能随时随地开关右键功能了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
          when 'share'
    button.share(type="button" title='分享链接' onclick="share()")
    i.fas.fa-share-nodes

    + when 'mouse'
    + button.share(type="button" title='右键模式' onclick="changeMouseMode()")
    + i.fas.fa-mouse


    #rightside
    - const { enable, hide, show } = theme.rightside_item_order
    - - const hideArray = enable ? hide && hide.split(',') : ['readmode','translate','darkmode']
    + - const hideArray = enable ? hide && hide.split(',') : ['readmode','translate','darkmode','hideAside', 'mouse']
    - const showArray = enable ? show && show.split(',') : ['toc','chat','share','comment']
  7. 重启项目看看效果(可能会有问题,因为这个还是比较复杂的,有问题在评论区留言吧!)

    1
    hexo cl; hexo s

本站页脚设置

  1. 首先要卸载店长的hexo-butterfly-footer-beautify插件,因为我将页脚直接写成一个pug,个人觉得插件很多冗余的地方用不到,因此卸载了,否则会冲突:

    1
    复制成功npm un hexo-butterfly-footer-beautify --save
  2. 在主题配置文件_config.butterfly.yml或者站点配置文件_config.yml删除插件相关的配置项:

    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
    -footer_beautify:
    - enable:
    - timer: true # 计时器开关
    - bdage: true # 徽标开关
    - priority: 5 #过滤器优先权
    - enable_page: all # 应用页面
    - exclude: #屏蔽页面
    - # - /posts/
    - # - /about/
    - layout: # 挂载容器类型
    - type: id
    - name: footer-wrap
    - index: 0
    - runtime_js: https://npm.elemecdn.com/hexo-butterfly-footer-beautify@1.0.0/lib/runtime.js
    - runtime_css: https://npm.elemecdn.com/hexo-butterfly-footer-beautify@1.0.0/lib/runtime.css
    - # 徽标部分配置项
    - swiperpara: 0 #若非0,则开启轮播功能,每行徽标个数
    - bdageitem:
    - - link: https://hexo.io/ #徽标指向网站链接
    - shields: https://img.shields.io/badge/Frame-Hexo-blue?style=flat&logo=hexo #徽标API
    - message: 博客框架为Hexo_v6.2.0 #徽标提示语
    - - link: https://butterfly.js.org/
    - shields: https://img.shields.io/badge/Theme-Butterfly-6513df?style=flat&logo=bitdefender
    - message: 主题版本Butterfly_v4.3.1
    - - link: https://vercel.com/
    - shields: https://img.shields.io/badge/Hosted-Vercel-brightgreen?style=flat&logo=Vercel
    - message: 本站采用多线部署,主线路托管于Vercel
    - - link: https://dashboard.4everland.org/
    - # https://img.shields.io/badge/Hosted-4EVERLAND-3FE2C1?style=flat&logo=IPFS
    - shields: https://img.shields.io/badge/Hosted-4EVERLAND-22DDDD?style=flat&logo=IPFS
    - message: 本站采用多线部署,备用线路托管于4EVERLAND
    - - link: https://github.com/
    - shields: https://img.shields.io/badge/Source-Github-d021d6?style=flat&logo=GitHub
    - message: 本站项目由Github托管
    - - link: http://creativecommons.org/licenses/by-nc-sa/4.0/
    - shields: https://img.shields.io/badge/Copyright-BY--NC--SA%204.0-d42328?style=flat&logo=Claris
    - message: 本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可
    - swiper_css: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.css
    - swiper_js: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.js
    - swiperbdage_init_js: https://npm.elemecdn.com/hexo-butterfly-footer-beautify/lib/swiperbdage_init.min.js
  3. [BlogRoot]/themes/butterfly/layout/includes/footer.pug替换成如下代码这块东西分为几个部分,一个是以#ft为块的DOM,其中分为了格言猜你想看推荐友链三部分,参考图中的位置结合自己的喜好进行修改即可,图像、文字和链接均替换成你自己的(记住不要用我的链接!!!);if theme.footer.owner.enable起这一块是主题指定的信息版权信息,我把主题配置项的copyrightcustom_text这两项留空了,因此只会显示©2022 By ;再然后就是#workboard这块,这块的信息由js逻辑写入与更新,可以自定义;最后是p#ghbdages这块,是徽标显示,大家可以到shields.io按照自己的信息生成(不要用我的!!!):

    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
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    复制成功
    #footer-wrap
    #ft
    .ft-item-1
    .t-top
    .t-t-l
    p.ft-t.t-l-t 格言🧬
    .bg-ad
    div
    | 再看看那个光点,它就在这里,这是家园,这是我们 —— 你所爱的每一个人,你认识的一个人,你听说过的每一个人,曾经有过的每一个人,都在它上面度过他们的一生✨
    .btn-xz-box
    a.btn-xz(href='https://stellarium.org/') 点击开启星辰之旅
    .t-t-r
    p.ft-t.t-l-t 猜你想看💡
    ul.ft-links
    li
    a(href='/posts/eec9786.html') 魔改指南
    a(href='/box/nav/') 网址导航
    li
    a(href='/social/link/') 我的朋友
    a(href='/comments/') 留点什么
    li
    a(href='/personal/about/') 关于作者
    a(href='/archives/') 文章归档
    li
    a(href='/categories/') 文章分类
    a(href='/tags/') 文章标签
    li
    a(href='/box/Gallery/') 我的画廊
    a(href='/personal/bb/') 我的唠叨
    li
    a(href='/site/time/') 建设进程
    a(href='/site/census/') 网站统计
    .ft-item-2
    p.ft-t 推荐友链⌛
    .ft-img-group
    .img-group-item
    a(href='https://www.fomal.cc/' title='Fomalhaut🥝')
    img(src='https://lskypro.acozycotage.net/LightPicture/2022/12/60e5d4e39da7c077.webp' alt='')
    .img-group-item
    a(href='https://tzy1997.com/' title='唐志远の博客')
    img(src='https://lskypro.acozycotage.net/LightPicture/2022/12/4ab83cdce942463b.jpg' alt='')
    .img-group-item
    a(href='https://akilar.top/' title='Akilarの糖果屋')
    img(src='https://lskypro.acozycotage.net/LightPicture/2022/12/6bf1ed05796db59c.jpg' alt='')
    .img-group-item
    a(href='https://butterfly.js.org/' title='Butterfly')
    img(src='https://lskypro.acozycotage.net/LightPicture/2022/12/64cc6a7d508026e1.png' alt='')
    .img-group-item
    a(href='https://anzhiy.cn/' title='安知鱼')
    img(src='https://lskypro.acozycotage.net/LightPicture/2022/12/1b33fef8f5fb7e63.jpg' alt='')
    .img-group-item
    a(href='https://www.acozycotage.net/' title='Acozycotage')
    img(src='https://lskypro.acozycotage.net/LightPicture/2022/12/6a6fe6ebfd19c465.jpg' alt='')
    .img-group-item
    a(href='https://cdn.netdun.net/' title='网盾星球')
    img(src='https://lskypro.acozycotage.net/LightPicture/2022/12/70dee3f9d1ca10f3.webp' alt='')
    .img-group-item
    a(href='javascript:void(0)' title='广告位招租')
    img(src='https://lskypro.acozycotage.net/LightPicture/2022/12/65307a5828af6790.webp' alt='')

    if theme.footer.owner.enable
    - var now = new Date()
    - var nowYear = now.getFullYear()
    if theme.footer.owner.since && theme.footer.owner.since != nowYear
    .copyright
    span!= `<b>&copy;${theme.footer.owner.since} - ${nowYear}</b>`
    span!= `<b>&nbsp;&nbsp;By ${config.author}</b>`
    else
    .copyright
    span!= `<b>&copy;${nowYear}</b>`
    span!= `<b>&nbsp;&nbsp;By ${config.author}</b>`
    if theme.footer.copyright
    .framework-info
    span= _p('footer.framework') + ' '
    a(href='https://hexo.io')= 'Hexo'
    span.footer-separator |
    span= _p('footer.theme') + ' '
    a(href='https://github.com/jerryc127/hexo-theme-butterfly')= 'Butterfly'
    if theme.footer.custom_text
    .footer_custom_text!=`${theme.footer.custom_text}`

    #workboard

    p#ghbdages
    a.github-badge(target='_blank' href="https://hexo.io/" style='margin-inline:5px' title="博客框架为Hexo_v6.3.0")
    img(src="https://sourcebucket.s3.ladydaily.com/badge/Frame-Hexo-blue.svg" alt='')

    a.github-badge(target='_blank' href="https://butterfly.js.org/" style='margin-inline:5px' title="主题版本Butterfly_v4.3.1")
    img(src="https://sourcebucket.s3.ladydaily.com/badge/Theme-Butterfly-6513df.svg" alt='')

    a.github-badge(target='_blank' href="https://vercel.com/" style='margin-inline:5px' title="本站采用多线部署,主线路托管于Vercel")
    img(src="https://sourcebucket.s3.ladydaily.com/badge/Hosted-Vercel-brightgreen.svg" alt='')

    a.github-badge(target='_blank' href="https://user.51.la/" style='margin-inline:5px' title="本站数据分析得益于51la技术支持")
    img(src="https://sourcebucket.s3.ladydaily.com/badge/Analytics-51la-3db1eb.svg" alt='')

    a.github-badge(target='_blank' href="https://icp.gov.moe/?keyword=20226665" style='margin-inline:5px' title="本站已加入萌ICP豪华套餐,萌ICP备20226665号")
    img(src="https://sourcebucket.s3.ladydaily.com/badge/萌ICP备-20226665-fe1384.svg" alt='')

    a.github-badge(target='_blank' href="https://bitiful.dogecast.com/buckets" style='margin-inline:5px' title="本网站经Service Worker分流至缤纷云对象存储")
    img(src=" https://sourcebucket.s3.ladydaily.com/badge/Bucket-缤纷云-9c62da.svg" alt='')

    a.github-badge(target='_blank' href="https://www.netdun.net/" style='margin-inline:5px' title="本站使用网盾星球提供CDN加速与防护")
    img(src="https://sourcebucket.s3.ladydaily.com/badge/CDN-网盾星球-fff2cc.svg" alt='')

    a.github-badge(target='_blank' href="https://github.com/" style='margin-inline:5px' title="本网站源码由Github提供存储仓库")
    img(src=" https://sourcebucket.s3.ladydaily.com/badge/Source-Github-d021d6.svg" alt='')
  4. 将以下代码复制到自定义的custom.css中,其中颜色、圆角等可以根据你自己的喜好进行修改:

    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
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    复制成功
    /* tzy页脚样式 */
    #ft {
    max-width: 1200px;
    margin: 0 auto 12px;
    display: flex;
    color: rgb(255 255 255 / 80%) !important;
    text-align: left;
    flex-wrap: wrap;
    }

    .ft-item-1,
    .ft-item-2 {
    display: flex;
    height: 100%;
    padding: 2px 14px;
    }

    .ft-item-1 {
    flex-direction: column;
    flex: 2;
    }

    .ft-item-2 {
    flex: 1;
    flex-direction: column;
    }

    .t-top {
    display: flex;
    }

    .t-top .t-t-l {
    display: flex;
    flex-direction: column;
    flex: 1.4;
    margin-right: 10px;
    }

    .t-top .t-t-l .bg-ad {
    width: 85%;
    border-radius: 10px;
    padding: 0 10px;
    }

    .btn-xz-box {
    margin-top: 10px;
    }

    /* 按钮背景颜色等 */
    .btn-xz {
    display: block;
    background-color: var(--btn-bg);
    color: var(--btn-color);
    text-align: center;
    line-height: 2.4;
    margin: 8px 0;
    }

    .btn-xz:hover {
    text-decoration: none !important;
    }
    /* 按钮悬浮颜色 */
    .btn-xz-box:hover .btn-xz {
    background-color: var(--text-bg-hover);
    }

    .t-top .t-t-r {
    display: flex;
    flex-direction: column;
    flex: 1;
    }

    .ft-links {
    padding: 0 14px;
    list-style: none;
    margin-top: 0 !important;
    }

    .ft-links li a {
    display: inline-block !important;
    width: 50%;
    }
    /* 链接悬浮颜色 */
    .ft-links li a:hover {
    text-decoration: none !important;
    color: var(--theme-color) !important;
    }

    .ft-item-2 .ft-img-group {
    width: 100%;
    }

    .ft-t {
    font-size: 1.1rem;
    margin-bottom: 20px;
    line-height: 1;
    font-weight: 600;
    }

    .t-l-t {
    padding-left: 14px;
    }

    .ft-item-2 .ft-img-group .img-group-item {
    display: inline-block;
    width: 18.4%;
    margin-right: 14px;
    margin-bottom: 6px;
    }

    .ft-item-2 .ft-img-group .img-group-item a {
    display: inline-block;
    width: 100%;
    height: 100%;
    }

    .ft-item-2 .ft-img-group .img-group-item a img {
    width: 100%;
    max-height: 80px;
    border-radius: 10px;
    }
    /* 头像悬浮颜色框 */
    .ft-item-2 .ft-img-group .img-group-item a img:hover {
    border: 2px solid var(--theme-color);
    }

    @media screen and (max-width: 768px) {
    .ft-item-1 {
    flex-basis: 100% !important;
    }

    .ft-item-2 {
    flex-basis: 100% !important;
    }

    .t-top .t-t-l .bg-ad {
    width: 100%;
    }
    }

    @media screen and (max-width: 576px) {
    .t-top {
    flex-wrap: wrap;
    }

    .t-top .t-t-l {
    flex-basis: 100% !important;
    }

    .t-top .t-t-r {
    margin-top: 16px;
    flex-basis: 100% !important;
    }
    }
    #footer-wrap a {
    border-radius: 30px;
    }
    #footer-wrap {
    padding: 20px 20px;
    }

    /* 页脚心跳动画 */
    #heartbeat {
    color: red;
    animation: iconAnimate 1s ease-in-out infinite;
    }
    @-moz-keyframes iconAnimate {
    0%,
    100% {
    transform: scale(1);
    }
    10%,
    30% {
    transform: scale(0.9);
    }
    20%,
    40%,
    60%,
    80% {
    transform: scale(1.1);
    }
    50%,
    70% {
    transform: scale(1.1);
    }
    }
    @-webkit-keyframes iconAnimate {
    0%,
    100% {
    transform: scale(1);
    }
    10%,
    30% {
    transform: scale(0.9);
    }
    20%,
    40%,
    60%,
    80% {
    transform: scale(1.1);
    }
    50%,
    70% {
    transform: scale(1.1);
    }
    }
    @-o-keyframes iconAnimate {
    0%,
    100% {
    transform: scale(1);
    }
    10%,
    30% {
    transform: scale(0.9);
    }
    20%,
    40%,
    60%,
    80% {
    transform: scale(1.1);
    }
    50%,
    70% {
    transform: scale(1.1);
    }
    }
    @keyframes iconAnimate {
    0%,
    100% {
    transform: scale(1);
    }
    10%,
    30% {
    transform: scale(0.9);
    }
    20%,
    40%,
    60%,
    80% {
    transform: scale(1.1);
    }
    50%,
    70% {
    transform: scale(1.1);
    }
    }
  5. 然后计时器还要往#footer-wrap这块元素上面写入网站运行时间等信息,新建文件[BlogRoot]\source\js\runtime.js,写入如下代码。这里要修改的几块东西是:网站诞生时间currentTimeHtml这块东西;其中currentTimeHtml分为了两种模式,对应两个不同的图标,自行研究一下就懂!

    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
    复制成功
    var now = new Date();
    function createtime() {
    // 当前时间
    now.setTime(now.getTime() + 1000);
    var start = new Date("08/01/2022 00:00:00"); // 旅行者1号开始计算的时间
    var dis = Math.trunc(23400000000 + ((now - start) / 1000) * 17); // 距离=秒数*速度 记住转换毫秒
    var unit = (dis / 149600000).toFixed(6); // 天文单位
    var grt = new Date("08/09/2022 00:00:00"); // 网站诞生时间
    var days = (now - grt) / 1e3 / 60 / 60 / 24,
    dnum = Math.floor(days),
    hours = (now - grt) / 1e3 / 60 / 60 - 24 * dnum,
    hnum = Math.floor(hours);
    1 == String(hnum).length && (hnum = "0" + hnum);
    var minutes = (now - grt) / 1e3 / 60 - 1440 * dnum - 60 * hnum,
    mnum = Math.floor(minutes);
    1 == String(mnum).length && (mnum = "0" + mnum);
    var seconds = (now - grt) / 1e3 - 86400 * dnum - 3600 * hnum - 60 * mnum,
    snum = Math.round(seconds);
    1 == String(snum).length && (snum = "0" + snum);
    let currentTimeHtml = "";
    (currentTimeHtml =
    hnum < 18 && hnum >= 9
    ? `<img class='boardsign' src='https://sourcebucket.s3.ladydaily.com/badge/F小屋-科研摸鱼中.svg' title='什么时候能够实现财富自由呀~'><br> <div style="font-size:13px;font-weight:bold">本站居然运行了 ${dnum}${hnum} 小时 ${mnum}${snum} 秒 <i id="heartbeat" class='fas fa-heartbeat'></i> <br> 旅行者 1 号当前距离地球 ${dis} 千米,约为 ${unit} 个天文单位 🚀</div>`
    : `<img class='boardsign' src='https://sourcebucket.s3.ladydaily.com/badge/F小屋-下班休息啦.svg' title='下班了就该开开心心地玩耍~'><br> <div style="font-size:13px;font-weight:bold">本站居然运行了 ${dnum}${hnum} 小时 ${mnum}${snum} 秒 <i id="heartbeat" class='fas fa-heartbeat'></i> <br> 旅行者 1 号当前距离地球 ${dis} 千米,约为 ${unit} 个天文单位 🚀</div>`),
    document.getElementById("workboard") &&
    (document.getElementById("workboard").innerHTML = currentTimeHtml);
    }
    // 设置重复执行函数,周期1000ms
    setInterval(() => {
    createtime();
    }, 1000);
  6. 在主题配置文件_config.butterfly.yml引入该runtime.js文件:

    1
    2
    3
    inject:
    bottom:
    + - <script defer src="/js/runtime.js"></script> # 页脚计时器
  7. 到这里你已经成功了 99.99%,最后重新编译运行即可看见效果

    1
    hexo cl; hexo s

信息卡片头像状态

  1. 修改[BlogRoot]\themes\butterfly\layout\includes\widget\card_author.pug

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    if theme.aside.card_author.enable
    .card-widget.card-info
    .is-center
    - .avatar-img
    - img(src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt="avatar")
    + div.card-info-avatar
    + .avatar-img
    + img(src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt="avatar")
    + div.author-status-box
    + div.author-status
    + g-emoji.g-emoji(alias="palm_tree" fallback-src="https://lskypro.acozycotage.net/LightPicture/2022/12/fe1dc0402e623096.jpg") 🐟
    + span 认真摸鱼中

    其实原理很简单,就是创建了一个新的容器把头像和容器都包住,再用css调节样式就行。🐟那里可以换成任意一个emoji,在win10下只要win+.就可以输入emoji,认真摸鱼中就是对这个状态的描述,建议长度和这个接近,fallback-src是备用链接,当有设备不支持这个emoji时候就用那个图,可以是该emoji的小截图

  2. custom.css中引入以下样式,可以自己进行微调:

    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
    .card-info-avatar .author-status-box {
    position: absolute;
    bottom: 0;
    left: calc(100% - 28px);
    width: 28px;
    height: 28px;
    border: 1px solid #d0d7de;
    border-radius: 2em;
    background-color: #f8f8f8f8;
    transition: 0.4s;
    overflow: hidden;
    }

    [data-theme="dark"] .card-info-avatar .author-status-box {
    background-color: #222222f2;
    border: 1px solid #5c6060;
    }

    .card-info-avatar .author-status-box .author-status {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 28px;
    padding: 0 5px;
    }

    .card-info-avatar .author-status-box:hover {
    width: 105px;
    }

    .card-info-avatar .author-status-box:hover .author-status span {
    width: 105px;
    margin-left: 4px;
    }

    .card-info-avatar .author-status-box .author-status span {
    width: 0;
    font-size: 12px;
    height: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    transition: 0.4s;
    }

    .card-widget .card-info-avatar {
    display: inline-block;
    position: relative;
    }
  3. 重启项目

    1
    hexo cl; hexo s

头像呼吸灯

  1. 这个可以用js实现,也可以用纯css的关键帧实现,貌似css的性能会高点,在custom.css添加如下代码,颜色和时间啥的大家可以根据自己的喜好调节,其实就是关键帧之间通过某个插值方法连续变样式而已,会这一个你就会DIY各种高大上的动画啦

    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
    /* 头像呼吸灯 */
    [data-theme="light"] .avatar-img {
    animation: huxi_light 4s ease-in-out infinite;
    }
    [data-theme="dark"] .avatar-img {
    animation: huxi_dark 4s ease-in-out infinite;
    }
    @keyframes huxi_light {
    0% {
    box-shadow: 0px 0px 1px 1px #e9f5fa;
    }
    50% {
    box-shadow: 0px 0px 5px 5px #e9f5fa;
    }
    100% {
    box-shadow: 0px 0px 1px 1px #e9f5fa;
    }
    }
    @keyframes huxi_dark {
    0% {
    box-shadow: 0px 0px 1px 1px #39c5bb;
    }
    50% {
    box-shadow: 0px 0px 5px 5px #39c5bb;
    }
    100% {
    box-shadow: 0px 0px 1px 1px #39c5bb;
    }
    }
  2. 重启项目即可看到效果

    1
    hexo cl; hexo s

网站恶搞标题

  1. 新建文件[BlogRoot]\source\js\title.js,写入以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    //动态标题
    var OriginTitile = document.title;
    var titleTime;
    document.addEventListener('visibilitychange', function () {
    if (document.hidden) {
    //离开当前页面时标签显示内容
    document.title = '👀跑哪里去了~';
    clearTimeout(titleTime);
    } else {
    //返回当前页面时标签显示内容
    document.title = '🐖抓到你啦~';
    //两秒后变回正常标题
    titleTime = setTimeout(function () {
    document.title = OriginTitile;
    }, 2000);
    }
    });
  2. 在主题配置文件_config.butterfly.yml引入该文件:

    1
    2
    3
    inject: 
    bottom:
    + - <script async src="/js/title.js"></script>
  3. 重启项目:

    1
    hexo cl; hexo s

右边滚动栏样式

custom.css中加入以下代码,其中var(--theme-color)换成你自己的主题色:

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
/* 滚动条样式 */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}

::-webkit-scrollbar-track {
background-color: rgba(73, 177, 245, 0.2);
border-radius: 2em;
}

::-webkit-scrollbar-thumb {
background-color: var(--theme-color);
background-image: -webkit-linear-gradient(
45deg,
rgba(255, 255, 255, 0.4) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.4) 50%,
rgba(255, 255, 255, 0.4) 75%,
transparent 75%,
transparent
);
border-radius: 2em;
}

::-webkit-scrollbar-corner {
background-color: transparent;
}

::-moz-selection {
color: #fff;
background-color: var(--theme-color);
}

标签云增加文章数上下标

Butterfly 标签云增加文章数上下标 | Eurkon

前言

本文教程主要针对 Hexo Butterfly 主题博客,在 Butterfly 主题中,文章标签页标签侧边栏都有文章标签的词云图,但仅仅用字体大小表示某个标签下的文章数量是不明显的,可以在这个基础上加上表示某个标签下文章数的上下标,其中 <sup> 表示上标,<sub> 表示下标。

修改 page.js

  1. 打开 \themes\butterfly\layout\includes\page\tags.pug 文件和 \themes\butterfly\layout\includes\widget\card_tags.pug 文件,发现绘制彩色标签云都是使用了 cloudTags 函数。

    另外一个绘制标签云的 tagcloud 函数是 hexo 自带的,有兴趣的可以到 \node_modules\hexo\lib\plugins\helper\tagcloud.js 研究,这里不多介绍。

  2. 搜索 cloudTags 函数,可以在 \themes\butterfly\scripts\helpers\page.js 找到绘制标签云的代码,增加 <sup>${tag.length}</sup><sub>${tag.length}</sub> 可绘制表示标签文章数的上下标。

    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
    hexo.extend.helper.register('cloudTags', function (options = {}) {
    const theme = hexo.theme.config
    const env = this
    let source = options.source
    const minfontsize = options.minfontsize
    const maxfontsize = options.maxfontsize
    const limit = options.limit
    const unit = options.unit || 'px'

    let result = ''
    if (limit > 0) {
    source = source.limit(limit)
    }

    const sizes = []
    source.sort('length').forEach(tag => {
    const { length } = tag
    if (sizes.includes(length)) return
    sizes.push(length)
    })

    const length = sizes.length - 1
    source.forEach(tag => {
    const ratio = length ? sizes.indexOf(tag.length) / length : 0
    const size = minfontsize + ((maxfontsize - minfontsize) * ratio)
    let style = `font-size: ${parseFloat(size.toFixed(2))}${unit};`
    const color = 'rgb(' + Math.floor(Math.random() * 201) + ', ' + Math.floor(Math.random() * 201) + ', ' + Math.floor(Math.random() * 201) + ')' // 0,0,0 -> 200,200,200
    style += ` color: ${color}`
    - result += `<a href="${env.url_for(tag.path)}" style="${style}">${tag.name}</a>`
    + result += `<a href="${env.url_for(tag.path)}" style="${style}">${tag.name}<sup>${tag.length}</sup></a>`
    })
    return result
    })

Hexo 三连

执行 Hexo 三连

1
hexo clean && hexo g && hexo s