Featured image of post Hugo 博客功能拓展

Hugo 博客功能拓展

博客搭建完成后,来探索一下Hugo的更多有趣玩法

博客搭建过程见Hugo + Github博客搭建记录

点赞

创建点赞数据库

注册并登录LeanCloud 控制台

点击创建应用,填写名称,选择开发版(免费)

点击应用左下角数据存储,然后点击创建Class

类名填Like,注意首字母大写,其他设置如下

点击Like>添加列

字段名 类型 描述
path String 页面唯一路径
count Number 点赞数量

点击左下角设置>应用凭证,记录自己的AppIDAppKeyAPI 服务器地址

设置

Tabler Icons下载点赞图标命名为thumb-up,放在static/icons

layouts/partials下创建like.html,加入以下代码

  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
{{ if eq .Kind "page" }}
  <div id="like-container">
    <img id="like-icon" src="/icons/thumb-up.svg" alt="Like" />
    <span id="like-count">0</span>
  </div>

  <style>
    #like-container {
      text-align: center;
      margin: -2.5rem 0 -5rem 0rem;
      user-select: none;
      color: white;
    }

    #like-icon {
      width: 33px;
      height: 36px;
      cursor: pointer;
      transition: transform 0.15s ease;
      filter: brightness(0) invert(1);
    }

    #like-icon.clicked {
      animation: bounce 0.4s ease;
    }

    @keyframes bounce {
      0%   { transform: scale(1); }
      50%  { transform: scale(1.4); }
      100% { transform: scale(1); }
    }

    #like-count {
      display: inline-block;
      margin-left: 0px;
      font-size: 1.5rem; 
    }
  </style>

  <script>
  (function () {
    const appId = 'QMq4HFQshcHbTkGqUoX10lDK-gzGzoHsz';
    const appKey = 'MgjYDq8Uwr9g8x8HEJ24tyEB';
    const serverURL = 'https://qmz4hfqs.lc-cn-n1-shared.com';

    const pagePath = window.location.pathname;
    const localKey = 'liked_' + pagePath;
    const maxLikes = 50;
    const headers = {
      'X-LC-Id': appId,
      'X-LC-Key': appKey,
      'Content-Type': 'application/json'
    };

    async function fetchLike() {
      const res = await fetch(`${serverURL}/1.1/classes/Like?where=` + encodeURIComponent(JSON.stringify({ path: pagePath })), { headers });
      const data = await res.json();
      if (data.results.length > 0) {
        return data.results[0];
      } else {
        const resNew = await fetch(`${serverURL}/1.1/classes/Like`, {
          method: 'POST',
          headers,
          body: JSON.stringify({
            path: pagePath,
            count: 0,
            ACL: {
              "*": {
                "read": true,
                "write": true
              }
            }
          })
        });
        return await resNew.json();
      }
    }

    async function increaseLike(objectId) {
      await fetch(`${serverURL}/1.1/classes/Like/${objectId}`, {
        method: 'PUT',
        headers,
        body: JSON.stringify({ count: { __op: 'Increment', amount: 1 } })
      });
    }

    document.addEventListener('DOMContentLoaded', async () => {
      const icon = document.getElementById('like-icon');
      const count = document.getElementById('like-count');
      const likedCount = parseInt(localStorage.getItem(localKey) || '0');

      const data = await fetchLike();
      count.textContent = data.count || 0;

      icon.addEventListener('click', async () => {
        let current = parseInt(localStorage.getItem(localKey) || '0');
        if (current >= maxLikes) return;

        icon.classList.add('clicked');
        setTimeout(() => icon.classList.remove('clicked'), 400);

        count.textContent = parseInt(count.textContent) + 1;
        localStorage.setItem(localKey, current + 1);
        await increaseLike(data.objectId);
      });
    });
  })();
  </script>
{{ end }}

layouts/_default/single.html中, {{ partial "comments/include" . }}这一句之后添加{{ partial "like.html" . }},也可调整顺序来改变点赞按钮位置

背景

动态球

layouts/partials/footer/custom.html中加入

1
2
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.js"></script>
<script src="https://cdn.jsdelivr.net/gh/theme-next/theme-next-three@latest/canvas_sphere.min.js" ></script>

粒子

这里自行设置,detect_on要改成 window,然后下载配置文件与js文件

解压文件,将 particles.min.jsparticlesjs-config.json 放在 assets/background 文件夹下

layouts/partials/footer/custom.html 中加入

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<div id="particles-js"></div>

<script src={{ (resources.Get "background/particles.min.js").Permalink }}></script>
<script>
  particlesJS.load('particles-js', {{ (resources.Get "background/particlesjs-config.json").Permalink }}, function() {
    console.log('particles.js loaded - callback');
  });
</script>

<style>
  #particles-js {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    z-index: -1;
  }
</style>

底部小鱼

renderer.js保存到static/js/下。

layouts/partials/footer/custom.html 中加入

 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
<div id="jsi-flying-fish-container"></div>

<script src="{{ "/js/renderer.js" | relURL }}"></script>

<style>
    #jsi-flying-fish-container {
        width: 100%;
        height: 200px;
        position: absolute;
        bottom: 0;
        left: 0;
        z-index: -1;
        opacity: 0.37;
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }
	    html, body {
      	  position: relative;
   	      min-height: 100%;
        }  
    /* 确保主要内容区域是相对定位的容器 */
    body {
        position: relative;
    }
</style>

<script>
  if (typeof RENDERER !== 'undefined') {
    RENDERER.init();
  }
</script>

背景图片

将背景图放在assets/background

layouts/partials/footer/custom.html中加入以下代码,并修改图片名

1
2
3
4
5
6
7
<style>
  body {
    background: url({{ (resources.Get "background/图片名").Permalink }}) no-repeat center top;
    background-size: cover;
    background-attachment: fixed;
  }
</style>

视觉效果

无说明的部分在assets/scss/custom.scss 中加入代码

字体

100font下载字体,然后把文件放到static/font

layouts/partials/footer/custom.html中加入以下代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<style>
  @font-face {
    font-family: '字体名';
      src: url('{{ "font/字体名.ttf" | relURL }}') format('opentype');
  } /这部分可以复制粘贴并修改名字增加字体

  :root {
    --base-font-family: '字体名';	/文章字体
    --code-font-family: '字体名';	/代码块字体
  }
</style>

鼠标样式

将鼠标样式图片放入static/mouse

加入以下代码并修改对应图片名

 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
// default光标图片
body,
html,
.article-content img {
  cursor: url(../mouse/默认光标图片名),
  auto !important;
}

// pointer光标图片
a:hover,
button:hover,
.copyCodeButton:hover,
#dark-mode-toggle {
  cursor: url(../mouse/指针光标图片名),
  auto;
}

// text光标图片
input:hover,
.site-description,
.article-subtitle,
.article-content span,
.article-content li,
.article-content p {
  cursor: url(../mouse/文本光标图片名),
  auto;
}

布局

 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
// 文章封面高度
.article-list article .article-image img {
  width: 100%;
  height: 200px !important;
  object-fit: cover;

  @include respond(md) {
      height: 250px !important;
  }

  @include respond(xl) {
      height: 285px !important;
  }
}

// 全局页面布局间距调整
.main-container {
  min-height: 100vh;
  align-items: flex-start;
  padding: 0 15px;
  gap: var(--section-separation);
  padding-top: var(--main-top-padding);

  @include respond(md) {
    padding: 0 37px;
  }
}

配色

 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
// 页面基本配色
:root {
  // 全局顶部边距
  --main-top-padding: 30px;
  // 全局卡片圆角
  --card-border-radius: 25px;
  // 标签云卡片圆角
  --tag-border-radius: 8px;
  // 卡片间距
  --section-separation: 40px;
  // 全局字体大小
  --article-font-size: 1.8rem;
  // 行内代码背景色
  --code-background-color: #f8f8f8;
  // 行内代码前景色
  --code-text-color: #e96900;
  // 暗色模式下样式
  &[data-scheme="dark"] {
    // 行内代码背景色
    --code-background-color: #ff6d1b17;
    // 行内代码前景色
    --code-text-color: #e96900;
    // 暗黑模式下背景色
    --body-background: #000;
    // 暗黑模式下卡片背景色
    --card-background: hsl(225 13% 8% / 1);
  }
}

// 设置选中字体的区域背景颜色
//修改选中颜色
::selection {
  color: #fff;
  background: #34495e;
}

a {
  text-decoration: none;
  color: var(--accent-color);

  &:hover {
    color: var(--accent-color-darker);
  }

  &.link {
    color: #4288b9ad;
    font-weight: 600;
    padding: 0 2px;
    text-decoration: none;
    cursor: pointer;

    &:hover {
      text-decoration: underline;
    }
  }
}

//文章背景颜色
.content,
article,
.article-content {
    background: hwb(234 13% 83% / 0.737) !important;
}

.pagination,
.page-link {
    background: hwb(255 15% 79% / 0.659) !important;
}

.widget--toc,
.widget--toc .widget__content {
    background:  hwb(235 13% 83% / 0.659) !important;
}

// 文章内容引用块样式
.article-content {
  blockquote {
    border-left: 6px solid #358b9a1f !important;
    background: #3a97431f;
  }
}

滚动条美化

1
2
3
4
5
/* 全局滚动条样式 */
* {
  scrollbar-width: thin; 
  scrollbar-color: rgba(180, 120, 142, 0.3) #000000; /* 滑块颜色 | 背景颜色 */
}

归档页面两栏

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// 归档页面两栏
@media (min-width: 1024px) {
  .article-list--compact {
    display: grid;
    grid-template-columns: 1fr 1fr;
    background: none;
    box-shadow: none;
    gap: 1rem;

    article {
      background: var(--card-background);
      border: none;
      box-shadow: var(--shadow-l2);
      margin-bottom: 8px;
      border-radius: 16px;
    }
  }
}

其他

 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
// 修改首页搜索框样式
.search-form.widget input {
  font-size: 1.5rem;
  padding: 44px 25px 19px;
}

// 文章内容图片圆角阴影
.article-page .main-article .article-content {
  img {
    max-width: 96% !important;
    height: auto !important;
    border-radius: 8px;
  }
}

// 修复引用块内容窄页面显示问题
a {
  word-break: break-all;
}

code {
  word-break: break-all;
}

// 代码块样式修改
.highlight {
  max-width: 102% !important;
  background-color: var(--pre-background-color);
  padding: var(--card-padding);
  position: relative;
  border-radius: 20px;
  margin-left: -7px !important;
  margin-right: -12px;
  box-shadow: var(--shadow-l1) !important;

  &:hover {
    .copyCodeButton {
      opacity: 1;
    }
  }

  // keep Codeblocks LTR
  [dir="rtl"] & {
    direction: ltr;
  }

  pre {
    margin: initial;
    padding: 0;
    margin: 0;
    width: auto;
  }
}

//全局页面小图片样式微调
.article-list--compact article .article-image img {
  width: var(--image-size);
  height: var(--image-size);
  object-fit: cover;
  border-radius: 17%;
}

边栏调整

assets/scss/grid.scss 中加入代码

页面三栏宽度

 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
//页面三栏宽度调整
.container {
  margin-left: auto;
  margin-right: auto;

  .left-sidebar {
    order: -3;
    max-width: var(--left-sidebar-max-width);
  }

  .right-sidebar {
    order: -1;
    max-width: var(--right-sidebar-max-width);

    /// Display right sidebar when min-width: lg
    @include respond(lg) {
      display: flex;
    }
  }

  &.extended {
    @include respond(md) {
      max-width: 1024px;
      --left-sidebar-max-width: 25%;
      --right-sidebar-max-width: 22% !important;
    }

    @include respond(lg) {
      max-width: 1280px;
      --left-sidebar-max-width: 20%;
      --right-sidebar-max-width: 30%;
    }

    @include respond(xl) {
      max-width: 1453px; //1536px;
      --left-sidebar-max-width: 15%;
      --right-sidebar-max-width: 25%;
    }
  }

  &.compact {
    @include respond(md) {
      --left-sidebar-max-width: 25%;
      max-width: 768px;
    }

    @include respond(lg) {
      max-width: 1024px;
      --left-sidebar-max-width: 20%;
    }

    @include respond(xl) {
      max-width: 1280px;
    }
  }
}

左侧栏元素

 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
/* 左侧栏宽度 */
.sidebar.left-sidebar {
  max-width: 15% !important;
  flex: 0 0 15% !important;
}

/* 左侧菜单 */
.sidebar .menu {
    padding-top: 20px;
}
.sidebar .menu a {
    font-size: 16px;
    line-height: 1.0;
    padding: 5px 0;
    display: block;
}
.sidebar .menu a:hover {
    opacity: 0.8;
    transform: translateX(4px);
}

/* 隐藏头像旁表情 */
.sidebar .emoji,
.sidebar .avatar-emoji,
.sidebar .author-emoji {
    display: none !important;
}

/* 头像与间距 */
.sidebar.left-sidebar .site-avatar img {
  width: 140px !important;
  height: 140px !important;
  border-radius: 50%;
}
.sidebar.left-sidebar .site-avatar {
  margin-bottom: 40px;
}

/* 名字与签名 */
.sidebar .site-name a {
    font-size: 2rem;
    font-weight: 700;
}
.left-sidebar .site-meta .site-description {
  font-size: 1.5rem !important;
}

/* 社交链接图标 */
.sidebar.left-sidebar .menu-social li svg {
    width: 2.5rem !important;
    height: 2.5rem !important;
    margin-right: 3px !important;
}

统计

文章浏览量

layouts/partials/footer/custom.html中加入以下代码

1
<script defer src="https://cn.vercount.one/js"></script>

将浏览量的图标保存assets/icons

layouts/partials/article/components/footer.html中加入以下代码

 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
<div class="article-details">
    ...
    <footer class="article-time">
        ...
        <!-- 浏览量统计 -->
        <div id="viewCount">
            {{ partial "helper/icon" "eye" }}
            <time class="article-time--reading">
                <span id="vercount_value_page_pv">loading... </span>            </time>
        </div>
        <style>
            #viewCount,
            #viewCount * {
                color: #fff !important;   
            }
            #viewCount {
             position: absolute;  /* 绝对定位 */
             left: 280px;            
            transform: translateY(-50%) translateY(260px);
        }
        </style>
    </footer>
    ...
</div>

文章数量和字数

layout/partials/footer/footer.html<section class="powerby"> 中加入以下代码

1
2
3
4
5
6
7
{{ $articleCount := len .Site.RegularPages }}
        {{ $totalWordCount := 0 }}
        {{ range .Site.Pages }}
        {{ $totalWordCount = add $totalWordCount .WordCount }}
        {{ end }}

        <p>发布了 {{ $articleCount }} 篇文章 | 共 {{$totalWordCount}} 字</p>

站点统计信息

layout/partials/footer/footer.html 中加入以下代码

 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
<section class="count_info">
  <div>
      {{ T "footer.runtime1" }}
      <span id="ds" class="running-days number-highlight"></span>
      {{ T "footer.runtime2" }}
      <span id="hs" class="running-days number-highlight"></span>
      {{ T "footer.runtime3" }}
      <span id="ms" class="running-days number-highlight"></span>
      {{ T "footer.runtime4" }}
  </div>
  <div>
      {{$scratch := newScratch}}
      {{ range (where .Site.Pages "Kind" "page" )}}
      {{$scratch.Add "total" .WordCount}}
      {{ end }}
      {{ T "footer.count1" }} 
      <span class="number-highlight">{{ len (where .Site.RegularPages "Section" "post") }}</span> 
      {{ T "footer.count2" }} 
      <span class="number-highlight">{{ div ($scratch.Get "total") 1000.0 | lang.FormatNumber 2 }}</span> 
      k {{ T "footer.count3" }}
  </div>
  <div>
      <span id="busuanzi_container_site_pv">
          {{ T "footer.pv1" }}
          <span id="busuanzi_value_site_pv" class="number-highlight"></span>
          {{ T "footer.pv2" }}
      </span>
  </div>
</section>

<!-- Add blog running time -->
<script>
let s1 = '2025-01-01'; //website start date
s1 = new Date(s1.replace(/-/g, "/"));
let s2 = new Date();
let timeDifference = s2.getTime() - s1.getTime();

let days = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
let hours = Math.floor((timeDifference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60));

// 获取元素并设置内容和类名
const ds = document.getElementById('ds');
const hs = document.getElementById('hs');
const ms = document.getElementById('ms');

ds.innerHTML = days;
hs.innerHTML = hours;
ms.innerHTML = minutes;

// 确保运行时间的数字也有高亮样式(虽然模板中已经添加了类名,这里再次确认)
ds.classList.add('number-highlight');
hs.classList.add('number-highlight');
ms.classList.add('number-highlight');

// 为不蒜子访问量数据也添加高亮(当数据加载后)
const busuanziValue = document.getElementById('busuanzi_value_site_pv');
if (busuanziValue) {
    busuanziValue.classList.add('number-highlight');
}
</script>

添加字段,在i18n/zh-cn.yaml 中加入以下代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
footer:
    # 本博客已稳定运行1天2小时3分钟
    runtime1:
        other: 本站稳定运行:
    runtime2:
        other: 天
    runtime3:
        other: 小时
    runtime4:
        other: 分钟

    # 共发表x篇文章,总计y k字
    count1:
        other: 共发表文章数:
    count2:
        other: 篇 · 总计
    count3:
        other: 字

    # 本站总访问量X次
    pv1:
        other: 本站总访问量:
    pv2:
        other: 次

修改样式,在assets/scss/custom.scss 中加入以下代码

 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
/* 移除访问量容器的背景与边框 */
.count_info {
  background: none !important;
  border: none !important;
  padding: 0 !important;
  border-radius: 0 !important;
  transform: translateY(-66px);
  color: inherit;
}

/* dark 模式下统一字体颜色 */
[data-scheme="dark"] .count_info {
  background: none !important;
  border: none !important;
  padding: 0 !important;
  border-radius: 0 !important;
  color: #f8f8f8c7 !important;
  transform: translateY(-5px);
}

/* 设置数值颜色 */
.number-highlight {
  color: var(--hover-text-color);
  font-weight: 600;
}

特殊功能

代码块折叠

展开图片放到assets/icons目录下

layouts/partials/footer/custom.html加入以下代码

 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
<style>
    .highlight {
        /* 你可以根据需要调整这个高度 */
        max-height: 400px;
        overflow: hidden;
    }

    .code-show {
        max-height: none !important;
    }

    .code-more-box {
        width: 100%;
        padding-top: 78px;
        background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255, 255, 255, 0)), to(#fff));
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1;
    }

    .code-more-btn {
        display: block;
        margin: auto;
        width: 44px;
        height: 22px;
        background: #f0f0f5;
        border-top-left-radius: 8px;
        border-top-right-radius: 8px;
        padding-top: 6px;
        cursor: pointer;
    }

    .code-more-img {
        cursor: pointer !important;
        display: block;
        margin: auto;
        width: 22px;
        height: 16px;
    }
</style>

<script>
  function initCodeMoreBox() {
    let codeBlocks = document.querySelectorAll(".highlight");
    if (!codeBlocks) {
      return;
    }
    codeBlocks.forEach(codeBlock => {
      // 校验是否overflow
      if (codeBlock.scrollHeight <= codeBlock.clientHeight) {
        return;
      }
      // 元素初始化
      // codeMoreBox
      let codeMoreBox = document.createElement('div');
      codeMoreBox.classList.add('code-more-box');
      // codeMoreBtn
      let codeMoreBtn = document.createElement('span');
      codeMoreBtn.classList.add('code-more-btn');
      codeMoreBtn.addEventListener('click', () => {
        codeBlock.classList.add('code-show');
        codeMoreBox.style.display = 'none';
        // 触发resize事件,重新计算目录位置
        window.dispatchEvent(new Event('resize'))
      })
      // img
      let img = document.createElement('img');
      img.classList.add('code-more-img');
      img.src = {{ (resources.Get "icons/codeMore.png").Permalink }}
      // 元素添加
      codeMoreBtn.appendChild(img);
      codeMoreBox.appendChild(codeMoreBtn);
      codeBlock.appendChild(codeMoreBox)
    })
  }
  
  initCodeMoreBox();
</script>

返回顶部

layouts/partials/footer/components/script.html 中加入以下代码

 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
<!-- Add back to top button -->
<script>
    function backToTop() {
      document.documentElement.scrollIntoView({
        behavior: 'smooth',
      })
    }
  
    window.onload = function () {
      let scrollTop =
        this.document.documentElement.scrollTop || this.document.body.scrollTop
      let totopBtn = this.document.getElementById('back-to-top')
      if (scrollTop > 0) {
        totopBtn.style.display = 'inline'
      } else {
        totopBtn.style.display = 'none'
      }
    }
  
    window.onscroll = function () {
      let scrollTop =
        this.document.documentElement.scrollTop || this.document.body.scrollTop
      let totopBtn = this.document.getElementById('back-to-top')
      if (scrollTop < 200) {
        totopBtn.style.display = 'none'
      } else {
        totopBtn.style.display = 'inline'
        totopBtn.addEventListener('click', backToTop, false)
      }
    }
  </script>

layout/partials/footer/custom.html 中加入以下代码,可以修改按钮颜色

 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
<!-- Add back to top button -->
<a href="#" id="back-to-top" title="返回顶部"></a>

<!--返回顶部 CSS -->
<style>
  #back-to-top {
    display: none;
    position: fixed;
    bottom: 5px;
    right: 15px;
    width: 40px; /* Reduced size */
    height: 40px; /* Reduced size */
    border-radius: 50%; /* Circular button for modern look */
    background-color: var(--body-background);
    box-shadow: var(--shadow-l2);
    font-size: 20px; /* Adjusted for smaller button */
    text-align: center;
    line-height: 38px; /* Center align arrow */
    cursor: pointer;
    transition:
      transform 0.3s ease,
      background-color 0.3s ease; /* Added smooth interaction */
  }

  #back-to-top:before {
    content: "";
    display: inline-block;
    position: relative;
    transform: rotate(135deg);
    height: 8px; /* Reduced size */
    width: 8px; /* Reduced size */
    border-width: 0 0 2px 2px;
    border-color: var(--back-to-top-color);
    border-style: solid;
  }

  #back-to-top:hover {
    transform: scale(1.1); /* Slightly larger on hover */
    background-color: var(--accent-background); /* Optional hover effect */
  }

  #back-to-top:hover:before {
    border-color: var(--accent-color); /* Change arrow color on hover */
  }

  /* Responsive styles */
  @media screen and (max-width: 768px) {
    #back-to-top {
      bottom: 5px;
      right: var(--container-padding);
      width: 30px; /* Slightly smaller for mobile */
      height: 30px;
      font-size: 16px;
      line-height: 32px;
    }
  }

  @media screen and (min-width: 1024px) {
    #back-to-top {
      bottom: 10px;
      right: 20px;
    }
  }

  @media screen and (min-width: 1280px) {
    #back-to-top {
      bottom: 15px;
      right: 25px;
    }
  }

  @media screen and (min-width: 1536px) {
    #back-to-top {
      bottom: 15px;
      right: 25px;
      /* visibility: hidden; */
    }
  }
</style>

头像旋转

1
2
3
4
5
6
7
8
// 头像旋转动画
.sidebar header .site-avatar .site-logo {
  transition: transform 0.8s ease-in-out; // 旋转时间
}

.sidebar header .site-avatar .site-logo:hover {
  transform: rotate(360deg); // 旋转角度为360度
}

音乐

我希望音乐可以作为背景音乐,自动播放并循环,不受页面刷新影响,同时保持博客界面整洁。故没有采用音乐插件

layouts/partials/footer/footer.html中加入以下代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<audio id="bg-music" src="/music/Low Roar - I'll Keep Coming.mp3" autoplay loop style="display:none;"></audio>

<script>
  const audio = document.getElementById("bg-music");

  // 浏览器策略限制,等待用户交互后尝试播放
  document.addEventListener('DOMContentLoaded', function () {
    // 尝试播放
    const playPromise = audio.play();

    if (playPromise !== undefined) {
      playPromise.then(() => {
        console.log("音乐播放成功");
      }).catch((error) => {
        console.log("自动播放被浏览器阻止,等待用户点击");
        // 用户交互后再尝试播放
        document.addEventListener('click', () => {
          audio.play();
        }, { once: true });
      });
    }
  });
</script>

将mp3文件放在\static\music目录下

参考

【Hugo】Stack主题自定义修改

Hugo Stack 魔改美化 | Naive Koala

Stack主题的自定义 | L1nSn0w’s Log

Hugo + Stack 主题美化指南 🎨

Hugo Stack主题装修笔记

Like 0
本站已不稳定运行 小时 分钟
共发表文章 14 篇 ,总计 35.94 k 字
本站总访问量:
使用 Hugo 构建
主题 StackJimmy 设计