【Hexo】美化教程合集 1
AiGuoHou- 鉴于每个人的根目录名称都不一样,本帖博客根目录一律以
[BlogRoot]
指代。 - 本贴魔改均基于
butterfly
主题。 - 本帖涉及魔改源码的内容,会使用diff代码块标识,复制时请不要忘记删除前面的
+、-
符号。 - 因为
.pug
和.styl
以及.yml
等对缩进要求较为严格,请尽量不要使用记事本等无法提供语法高亮的文本编辑器进行修改。 - 本帖基于
Butterfly主题
进行魔改方案编写,因此请读者优先掌握Butterfly主题官方文档的内容后再来进行魔改。 - 魔改会过程常常引入自定义的css与js文件,方法见【Hexo】添加自定义css和js文件
1 直达底部按钮
点击查看教程
在[BlogRoot]\themes\butterfly\layout\includes\rightside.pug
做以下修改:
1 | button#go-up(type="button" title=_p("rightside.back_to_top")) |
2 网站恶搞标题
点击查看教程
-
新建文件
[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);
}
}); -
在主题配置文件
_config.butterfly.yml
引入该文件:1
2
3inject:
bottom:
+ - <script async src="/js/title.js"></script> -
重启项目:
1
hexo cl && hexo s
3 随机壁纸API汇总
点击查看教程
网上可以查到很多随机壁纸的API,但是很多都用不了或者是图片质量比较低,于是今天汇总了一些目前可以用的随机壁纸API,其中列出来的图片质量都是比较高的,可以放心食用,本站随机壁纸API模块用的都是这部分API。
1 | //IMGAPI |
API链接就是引号引着的部分,具体的参数可以到相应官网查看API文档,这部分已经通过测试,到目前为止都是可用的,并且壁纸质量比较高;尤其是必应
、unsplash
、picsum
这几个API的图片质量十分高,赶紧给你的网站换上随机壁纸吧!
4 语雀同款链接卡片
点击查看教程
- 在
[BlogRoot]\themes\butterfly\scripts\tag
文件夹下面新建link.js
并粘贴如下代码:
1 | /** |
- 在
[BlogRoot]\themes\butterfly\source\css\_tags
文件夹下面新建link.styl
并粘贴如下代码:
1 | .link_card |
- 注意:
内容不能有英文逗号
,不然会出bug
1 | <!-- 使用html是为了高亮代码,不必在意 --> |
参数 | 描述 | 默认值 |
---|---|---|
链接 | 如果连接中包含http则新标签打开,否则本标签页打开 | 无 |
标题 | 网站的标题 | 点击直达链接 |
图标 | 网站favicon链接 |
|
介绍 | 网站的description | 无 |
5 渐变色版权美化
点击查看教程
-
修改
[BlogRoot]\themes\butterfly\layout\includes\post\post-copyright.pug
,直接复制以下内容替换原文件内容。此处多次用到了三元运算符作为默认项设置,在确保有主题配置文件的默认项的情况下,也可以在相应文章的front-matter
中重新定义作者,原文链接,开源许可协议等内容。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
32if theme.post_copyright.enable && page.copyright !== false
- let author = page.copyright_author ? page.copyright_author : config.author
- let url = page.copyright_url ? page.copyright_url : page.permalink
- let license = page.license ? page.license : theme.post_copyright.license
- let license_url = page.license_url ? page.license_url : theme.post_copyright.license_url
.post-copyright
.post-copyright__title
span.post-copyright-info
h #[=page.title]
.post-copyright__type
span.post-copyright-info
a(href=url_for(url))= theme.post_copyright.decode ? decodeURI(url) : url
.post-copyright-m
.post-copyright-m-info
.post-copyright-a
h 作者
.post-copyright-cc-info
h=author
.post-copyright-c
h 发布于
.post-copyright-cc-info
h=date(page.date, config.date_format)
.post-copyright-u
h 更新于
.post-copyright-cc-info
h=date(page.updated, config.date_format)
.post-copyright-c
h 许可协议
.post-copyright-cc-info
a.icon(rel='noopener' target='_blank' title='Creative Commons' href='https://creativecommons.org/')
i.fab.fa-creative-commons
a(rel='noopener' target='_blank' title=license href=url_for(license_url))=license -
修改
[BlogRoot]\themes\butterfly\source\css\_layout\post.styl
,直接复制以下内容,替换原文件,这个文件就是自己调节样式的。其中,184
行是白天模式的背景色,这里默认是我网站的渐变色,大家可以根据自己的喜好调节;253
行是夜间模式的发光光圈颜色,大家也可以自行替换成自己喜欢的颜色: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
264beautify()
headStyle(fontsize)
padding-left: unit(fontsize + 12, 'px')
&:before
margin-left: unit((-(fontsize + 6)), 'px')
font-size: unit(fontsize, 'px')
&:hover
padding-left: unit(fontsize + 18, 'px')
h1,
h2,
h3,
h4,
h5,
h6
transition: all .2s ease-out
&:before
position: absolute
top: calc(50% - 7px)
color: $title-prefix-icon-color
content: $title-prefix-icon
line-height: 1
transition: all .2s ease-out
@extend .fontawesomeIcon
&:hover
&:before
color: $light-blue
h1
headStyle(20)
h2
headStyle(18)
h3
headStyle(16)
h4
headStyle(14)
h5
headStyle(12)
h6
headStyle(12)
ol,
ul
p
margin: 0 0 8px
li
&::marker
color: $light-blue
font-weight: 600
font-size: 1.05em
&:hover
&::marker
color: var(--pseudo-hover)
ul > li
list-style-type: circle
#article-container
word-wrap: break-word
overflow-wrap: break-word
a
color: $theme-link-color
&:hover
text-decoration: underline
img
display: block
margin: 0 auto 20px
max-width: 100%
transition: filter 375ms ease-in .2s
p
margin: 0 0 16px
iframe
margin: 0 0 20px
if hexo-config('anchor')
a.headerlink
&:after
@extend .fontawesomeIcon
float: right
color: var(--headline-presudo)
content: '\f0c1'
font-size: .95em
opacity: 0
transition: all .3s
&:hover
&:after
color: var(--pseudo-hover)
h1,
h2,
h3,
h4,
h5,
h6
&:hover
a.headerlink
&:after
opacity: 1
ol,
ul
ol,
ul
padding-left: 20px
li
margin: 4px 0
p
margin: 0 0 8px
if hexo-config('beautify.enable')
if hexo-config('beautify.field') == 'site'
beautify()
else if hexo-config('beautify.field') == 'post'
&.post-content
beautify()
> :last-child
margin-bottom: 0
#post
.tag_share
.post-meta
&__tag-list
display: inline-block
&__tags
display: inline-block
margin: 8px 8px 8px 0
padding: 0 12px
width: fit-content
border: 1px solid $light-blue
border-radius: 12px
color: $light-blue
font-size: .85em
transition: all .2s ease-in-out
&:hover
background: $light-blue
color: var(--white)
.post_share
display: inline-block
float: right
margin: 8px 0
width: fit-content
.social-share
font-size: .85em
.social-share-icon
margin: 0 4px
width: w = 1.85em
height: w
font-size: 1.2em
line-height: w
.post-copyright
position: relative
margin: 40px 0 10px
padding: 10px 16px
border: 1px solid var(--light-grey)
transition: box-shadow .3s ease-in-out
overflow: hidden
border-radius: 12px
background: linear-gradient(45deg, #f6d8f5, #c2f1f0, #f0debf);
&:before
background var(--heo-post-blockquote-bg)
position absolute
right -26px
top -120px
content '\f25e'
font-size 200px
font-family 'Font Awesome 5 Brands'
opacity .2
&:hover
box-shadow: 0 0 8px 0 rgba(232, 237, 250, .6), 0 2px 4px 0 rgba(232, 237, 250, .5)
.post-copyright
&-meta
color: $light-blue
font-weight: bold
&-info
padding-left: 6px
a
text-decoration: none
word-break: break-word
&:hover
text-decoration: none
.post-copyright-cc-info
color: $theme-color;
.post-outdate-notice
position: relative
margin: 0 0 20px
padding: .5em 1.2em
border-radius: 3px
background-color: $noticeOutdate-bg
color: $noticeOutdate-color
if hexo-config('noticeOutdate.style') == 'flat'
padding: .5em 1em .5em 2.6em
border-left: 5px solid $noticeOutdate-border
&:before
@extend .fontawesomeIcon
position: absolute
top: 50%
left: .9em
color: $noticeOutdate-border
content: '\f071'
transform: translateY(-50%)
.ads-wrap
margin: 40px 0
.post-copyright-m-info
.post-copyright-a,
.post-copyright-c,
.post-copyright-u
display inline-block
width fit-content
padding 2px 5px
[data-theme="dark"]
#post
.post-copyright
background #07080a
text-shadow #bfbeb8 0 0 2px
border 1px solid rgb(19 18 18 / 35%)
box-shadow 0 0 5px var(--theme-color)
animation flashlight 1s linear infinite alternate
.post-copyright-info
color #e0e0e4
#post
.post-copyright__title
font-size 22px
.post-copyright__notice
font-size 15px
.post-copyright
box-shadow 2px 2px 5px -
默认项的配置
-
作者:
[BlogRoot]\_config.yml
中的author
配置项1
2
3
4
5
6
7
8# Site
title: Akilarの糖果屋
subtitle: Akilar.top
description:
keywords:
author: Akilar #默认作者
language: zh-CN
timezone: '' -
许可协议:
[BlogRoot]\_config.butterfly.yml
中的license
和license_url
配置项1
2
3
4
5post_copyright:
enable: true
decode: true
license: CC BY-NC-SA 4.0
license_url: https://creativecommons.org/licenses/by-nc-sa/4.0/
-
-
页面覆写配置项,修改对应文章的
front-matter
1
2
3
4
5
6
7
8
9---
title: Copyright-beautify # 文章名称
date: 2021-03-02 13:52:46 # 文章发布日期
updated: 2023-11-25 12:27:56 # 文章更新日期
copyright_author: Nesxc # 作者覆写
copyright_url: https://www.nesxc.com/post/hexocc.html # 原文链接覆写
license: # 许可协议名称覆写
license_url: # 许可协议链接覆写
---
6 评论表情包放大
点击查看教程
其实实现的原理很简单,就是创建一个盒子,将表情包的内容放在盒子里面,然后控制盒子位置和显示隐藏即可。
-
新建文件
[BlogRoot]\source\js\emoji.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// 如果当前页有评论就执行函数
if (document.getElementById('post-comment')) owoBig();
// 表情放大
function owoBig() {
let flag = 1, // 设置节流阀
owo_time = '', // 设置计时器
m = 3; // 设置放大倍数
// 创建盒子
let div = document.createElement('div'),
body = document.querySelector('body');
// 设置ID
div.id = 'owo-big';
// 插入盒子
body.appendChild(div)
// 构造observer
let observer = new MutationObserver(mutations => {
for (let i = 0; i < mutations.length; i++) {
let dom = mutations[i].addedNodes,
owo_body = '';
if (dom.length == 2 && dom[1].className == 'OwO-body') owo_body = dom[1];
// 如果需要在评论内容中启用此功能请解除下面的注释
// else if (dom.length == 1 && dom[0].className == 'tk-comment') owo_body = dom[0];
else continue;
// 禁用右键(手机端长按会出现右键菜单,为了体验给禁用掉)
if (document.body.clientWidth <= 768) owo_body.addEventListener('contextmenu', e => e.preventDefault());
// 鼠标移入
owo_body.onmouseover = (e) => {
if (flag && e.target.tagName == 'IMG') {
flag = 0;
// 移入300毫秒后显示盒子
owo_time = setTimeout(() => {
let height = e.path[0].clientHeight * m, // 盒子高
width = e.path[0].clientWidth * m, // 盒子宽
left = (e.x - e.offsetX) - (width - e.path[0].clientWidth) / 2, // 盒子与屏幕左边距离
top = e.y - e.offsetY; // 盒子与屏幕顶部距离
if ((left + width) > body.clientWidth) left -= ((left + width) - body.clientWidth + 10); // 右边缘检测,防止超出屏幕
if (left < 0) left = 10; // 左边缘检测,防止超出屏幕
// 设置盒子样式
div.style.cssText = `display:flex; height:${height}px; width:${width}px; left:${left}px; top:${top}px;`;
// 在盒子中插入图片
div.innerHTML = `<img src="${e.target.src}">`
}, 300);
}
};
// 鼠标移出隐藏盒子
owo_body.onmouseout = () => { div.style.display = 'none', flag = 1, clearTimeout(owo_time); }
}
})
observer.observe(document.getElementById('post-comment'), { subtree: true, childList: true }) // 监听的 元素 和 配置项
} -
新建文件
[BlogRoot]\source\css\emoji.css
,写入如下内容(更推荐全部写在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#owo-big {
position: fixed;
align-items: center;
background-color: rgb(255, 255, 255);
border: 1px #aaa solid;
border-radius: 10px;
z-index: 9999;
display: none;
transform: translate(0, -105%);
overflow: hidden;
animation: owoIn 0.3s cubic-bezier(0.42, 0, 0.3, 1.11);
}
[data-theme=dark] #owo-big {
background-color: #4a4a4a
}
#owo-big img {
width: 100%;
}
/* 动画效果代码由 Heo:https://blog.zhheo.com/ 提供 */
@keyframes owoIn {
0% {
transform: translate(0, -95%);
opacity: 0;
}
100% {
transform: translate(0, -105%);
opacity: 1;
}
} -
引入
css
和js
文件,略 -
重启项目,略
7 Vue+Element样式弹窗
点击查看教程
-
在主题配置文件
[BlogRoot]\_config.butterfly.yml
中 引入Vue
和Element
相关依赖:1
2
3
4
5
6inject:
head:
+ - <link rel="stylesheet" href="https://cdn1.tianli0.top/npm/element-ui@2.15.6/packages/theme-chalk/lib/index.css"> # 引入组件库(f12)
bottom:
+ - <script async src="https://cdn1.tianli0.top/npm/vue@2.6.14/dist/vue.min.js"></script> # 引入VUE(f12)
+ - <script async src="https://cdn1.tianli0.top/npm/element-ui@2.15.6/lib/index.js"></script> # 引入ElementUI(f12) -
在你想要弹出弹窗的js代码中加入如下代码即可触发弹窗:
1
2
3
4
5
6
7
8
9
10
11
12
13new Vue({
data: function () {
this.$notify({
title: "你已被发现😜",
message: "小伙子,扒源记住要遵循GPL协议!",
position: 'top-left',
offset: 50,
showClose: true,
type: "warning",
duration: 5000
});
}
})-
notify
:弹窗类型,可以替换为message
(信息提示)和confirm
(二次确认提示) -
title
:弹窗标题,可以改为自定义标题 -
message
:弹窗信息,可以改为自定义内容 -
position
:弹出位置,bottom、top和left、right两两组合 -
offset
:偏移量,简单可以理解为与边界的距离 -
showClose
:是否显示关闭按钮 -
type
:提示类型,可选success/warning/info/error等 -
duration
:停留时间,弹出停留至消失的时间,单位ms详见:Vue中常用的提示信息
-
8 按键防抖
点击查看教程
我们的博客按钮非常多,可能你平时并不在意,如果你为f12按钮绑定了一个弹窗,那当你长按f12可能会无限触发弹窗,这就是没有做按键防抖的后果,我们的是静态博客,所以只消耗本地的资源,如果是有后端服务的,频繁触发某个逻辑可能会消耗服务器资源,因此我们必须在前端过滤这些非法操作,不能让其跑到后端!我这里用的是最初等的计时器对象来防抖,原理就是延迟某个时间再触发逻辑(例如300ms),如果这段时间内按键再次按下直接忽略。
-
在任意一个js文件引入以下代码(我是在
[BlogRoot]\source\js\custom.js
引入的),这个js文件的引入最好在前面,否则可能不能及时生效1
2
3
4
5
6
7// 防抖全局计时器
let TT = null; //time用来控制事件的触发
// 防抖函数:fn->逻辑 time->防抖时间
function debounce(fn, time) {
if (TT !== null) clearTimeout(TT);
TT = setTimeout(fn, time);
} -
将你需要防抖的函数
fn()
用debounce(fn, 300)
替代,防抖时间可以自定义,单位为ms,下面就是一个例子1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// 复制提醒
document.addEventListener("copy", function () {
debounce(function () {
new Vue({
data: function () {
this.$notify({
title: "哎嘿!复制成功🍬",
message: "若要转载最好保留原文链接哦,给你一个大大的赞!",
position: 'top-left',
offset: 50,
showClose: true,
type: "success",
duration: 5000
});
}
})
}, 300);
}) -
在主题配置文件引入以上js文件,具体过程略。这样写全局都是用一个计时器,考虑到我们的博客较为简单,这样做实测是没啥问题了,再也不怕手抖了!
9 夜间模式动画(店长)
点击查看教程
详见:夜间模式动画(店长)
-
新建
[BlogRoot]\themes\butterfly\layout\includes\custom\sun_moon.pug
,这部分其实实质上就是一个svg文件,通过js操作它的旋转显隐,淡入淡出实现动画效果。1
2
3
4
5
6
7
8
9svg(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') -
新建
[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
//按钮相关,对侧栏按钮做过魔改的可以调整这里的数值
.icon-V
padding 5px -
新建
[BlogRoot]\themes\butterfly\source\js\sun_moon.js
,去除了冗余代码,去jquery1
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
28function 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)
} -
修改
[BlogRoot]\themes\butterfly\layout\includes\head.pug
,在文件末位加上一行1
2
3
4
5
6
7
8
9
10//- 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 -
修改
[BlogRoot]\themes\butterfly\layout\includes\rightside.pug
,把原本的昼夜切换按钮替换掉1
2
3
4
5
6
7
8
9
10when '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') -
修改
[BlogRoot]\_config.butterfly.yml
,引入一下js1
2
3inject:
bottom:
+ - <script async src="/js/sun_moon.js"></script> -
重启项目并切换夜间模式即可看见效果
1
hexo cl; hexo s
10 夜间模式切换动画2.0
点击查看教程
逛博客看见别人的切换动画有月亮,而且颜色也很好看,于是一顿f12操作下大概看懂原理,再结合现在的动画改进一下就是了。(注意:在做本魔改前,请先完成店长的夜间模式切换动画,同时最好也要有引入Vue+Element弹窗。本动画是基于店长的样式改进的,加入了弯月,切换到夜间模式是太阳变月亮,切换到白天模式是月亮变太阳,同时背景颜色也改为了我喜欢的。)
-
替换原来的
[BlogRoot]\themes\butterfly\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
75function 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)
} -
替换原来的
[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.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
//按钮相关,对侧栏按钮做过魔改的可以调整这里的数值
// .icon-V
// padding 5px -
重启项目并切换夜间模式即可看到效果:
1
hexo cl; hexo s
11 Heo同款loading动画
点击查看教程
- 本教程适用于 Butterfly 主题 4.5 以上版本(实测为 4.7.0 版本)
- 增加了动画页面下有百分比数字加载的效果
-
修改
themes/butterfly/layout/includes/loading/fullpage-loading.pug
下方的图片链接记得换成自己的
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- loading_img = theme.preloader.avatar
#loading-box(onclick='document.getElementById("loading-box").classList.add("loaded")')
.loading-bg
img.loading-img(class='nolazyload' src=loading_img ? url_for(loading_img) : "https://cdn.staticaly.com/gh/HappyLeeCode/IMG@main/img/avatar.webp")
.loading-image-dot
#loading-percentage
| 0%
script.
const loadingPercentage = document.getElementById("loading-percentage");
loadingPercentage.style.color = "black";
let loadingPercentageTimer = setInterval(function() {
var progressBar = document.querySelector(".pace-progress");
if (!progressBar) return
var currentValue = progressBar.getAttribute("data-progress-text");
if (currentValue !== loadingPercentage.textContent) {
loadingPercentage.textContent = currentValue;
if (currentValue === "100%") {
clearInterval(loadingPercentageTimer);
}
}
}, 100);
const preloader = {
endLoading: () => {
document.body.style.overflow = 'auto';
document.getElementById('loading-box').classList.add("loaded")
},
initLoading: () => {
document.body.style.overflow = '';
document.getElementById('loading-box').classList.remove("loaded")
}
}
window.addEventListener('load',()=> { preloader.endLoading() })
if (!{theme.pjax && theme.pjax.enable}) {
document.addEventListener('pjax:send', () => { preloader.initLoading() })
document.addEventListener('pjax:complete', () => { preloader.endLoading() })
} -
修改
themes/butterfly/layout/includes/loading/index.pug
1
2
3
4
5
6
7if theme.preloader.source === 1
include ./fullpage-loading.pug
else if theme.preloader.source === 2
include ./pace.pug
else
include ./fullpage-loading.pug
include ./pace.pug -
新建
source/css/progress_bar.css
, 也可以不做这一步,那么最后一步中修改配置文件pace_css_url
这一项就要留空, 这一步是修改 pace 加载的胶囊 💊 样式用的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.pace {
-webkit-pointer-events: none;
pointer-events: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
z-index: 2000;
position: fixed;
margin: auto;
top: 10px;
left: 0;
right: 0;
height: 8px;
border-radius: 8px;
width: 4rem;
background: #eaecf2;
border: 1px #e3e8f7;
overflow: hidden;
}
.pace-inactive .pace-progress {
opacity: 0;
transition: 0.3s ease-in;
}
.pace .pace-progress {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
max-width: 200px;
position: absolute;
z-index: 2000;
display: block;
top: 0;
right: 100%;
height: 100%;
width: 100%;
background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
animation: gradient 1.5s ease infinite;
background-size: 200%;
}
.pace.pace-inactive {
opacity: 0;
transition: 0.3s;
top: -8px;
}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
} -
修改
themes/butterfly/source/css/_layout/loading.styl
, 注意其中 .loading-bg 那一项下的 background 可以自行修改为自己的色值。(这里其实就是在修改加载背景的颜色,例如我的颜色是浅蓝色:#B0E2FF)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
56if hexo-config('preloader')
.loading-bg
display: flex;
width: 100%;
height: 100%;
position: fixed;
background: #B0E2FF;
z-index: 1001;
opacity: 1;
transition: .3s;
#loading-box
.loading-img
width: 100px;
height: 100px;
border-radius: 50%;
margin: auto;
border: 4px solid #f0f0f2;
animation-duration: .3s;
animation-name: loadingAction;
animation-iteration-count: infinite;
animation-direction: alternate;
.loading-image-dot
width: 30px;
height: 30px;
background: #6bdf8f;
position: absolute;
border-radius: 50%;
border: 6px solid #fff;
top: 50%;
left: 50%;
transform: translate(18px, 24px);
#loading-percentage
position: absolute;
top: 67%;
left: 50%;
transform: translateX(-50%);
&::before
content: "「"
margin-right: 10px
&::after
content: "」"
margin-left: 10px
&.loaded
.loading-bg
opacity: 0;
z-index: -1000;
@keyframes loadingAction
0% {
opacity: 1;
}
100% {
opacity: .4;
} -
在
[BlogRoot]\source\css\custom.css
中添加以下代码,其中 background 的 url 即为 loading 的图片地址。(不会的同学参考 【Hexo】添加自定义css和js文件)1
2
3
4.loading-img {
background: url(https://cdn.staticaly.com/gh/HappyLeeCode/IMG@main/img/avatar.webp) no-repeat center center;
background-size: cover;
} -
最后修改
_config.butterfly.yml
中preloader
选项, 改完以后source: 1 为满屏加载,无 pace 胶囊;source: 2 为 pace 胶囊,无满屏动画;source: 3 是两者都启用。1
2
3
4
5
6
7
8
9# Loading Animation (加載動畫)
preloader:
enable: true
# source
# 1. fullpage-loading
# 2. pace (progress bar)
source: 3
# pace theme (see https://codebyzach.github.io/pace/)
pace_css_url: /css/progress_bar.css
12 自定义右键菜单(自用)
点击查看教程
详见:自定义右键菜单(自用)
右键菜单前置教程:按键防抖(必须)、昼夜切换动画(本站有)、随即文章实现,请完成这两个前置教程再来做这个,或者可以注释掉pug文件中对应的功能就不会出发相应不存在的函数了。
-
新建
[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
76
77
78
79
80
81#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='百度搜索'
a.rightMenu-item(href="javascript:rmf.searchinThisPage();")
i.fas.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='昼夜切换'
a.rightMenu-item(href="javascript:rmf.translate();")
i.fa.fa-language
span='繁简转换'
if is_post()||is_page()
a.rightMenu-item(href="javascript:rmf.switchReadMode();")
i.fa.fa-book
span='阅读模式'
a.rightMenu-item(href="/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='打印页面' -
然后在
[BlogRoot]/themes/butterfly/layout/includes/layout.pug
中引入(注意缩进,去掉+)1
2
3
4
5
6
7
8
9
10
11
12
13
14doctype 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 -
在自定义的
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;
} -
创建
[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
315
316
317
318
319
320
321
322function 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("go-up").setAttribute("style", "display:none");
btf.scrollToDest(0, 500);
}
rmf.translate = function () {
document.getElementById("translateLink").click();
}
rmf.searchinThisPage=()=>{
document.body.removeChild(mask);
document.getElementsByClassName("local-search-box--input")[0].value=window.getSelection().toString()
document.getElementsByClassName("search")[0].click()
var evt = document.createEvent("HTMLEvents");evt.initEvent("input", false, false);document.getElementsByClassName("local-search-box--input")[0].dispatchEvent(evt);
}
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);
}
} -
引入jQuery依赖以及上述的css和js文件(
custom.css
默认已经引入了就不重复引用了)1
2
3
4inject:
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> -
本来到这里重启项目就可以见效了,我这里还加了一个右键开关,取消了原来ctrl复合的右键开关策略。因此还需要加一个右键开关的按钮,在
[BlogRoot]\themes\butterfly\layout\includes\rightside.pug
中做如下的修改,目的就是把鼠标开关放到右边栏的设置隐藏项里面,这样我们就能随时随地开关右键功能了1
2
3
4
5
6
7
8
9
10
11
12
13
14
15when 'comment'
if commentsJsLoad
a#to_comment(href="#post-comment" title=_p("rightside.scroll_to_comment"))
i.fas.fa-comments
+ 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'] -
重启项目看看效果(可能会有问题,因为这个还是比较复杂的,有问题在评论区留言吧!)
1
hexo cl; hexo s