新建hideAsideOnMobile.js

路径:[Blogroot]\source\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
// 固定卡片点击动作
function FixedCardWidget(type,name,index){
// 根据id或class选择元素
if (type === "id"){
var tempcard = document.getElementById(name);
}
else{
var tempcard = document.getElementsByClassName(name)[index];
}
// 若元素存在
if (tempcard) {
// 首先判断是否存在fixed-card-widget类
if (tempcard.className.indexOf('fixed-card-widget') > -1){
// 存在则移除
RemoveFixedCardWidget();
}
else{
// 不存在则先初始化防止卡片叠加
RemoveFixedCardWidget();
//新建退出蒙版
CreateQuitBox();
// 再添加固定卡片样式
tempcard.classList.add('fixed-card-widget');
}
}
}
//创建一个蒙版,作为退出键使用
function CreateQuitBox(){
var quitBox = `<div id="quit-box" onclick="RemoveFixedCardWidget()"></div>`
var asideContent = document.getElementById('aside-content');
asideContent.insertAdjacentHTML("beforebegin",quitBox)
}
// 移除卡片方法
function RemoveFixedCardWidget(){
var activedItems = document.querySelectorAll('.fixed-card-widget');
if (activedItems) {
for (i = 0; i < activedItems.length; i++) {
activedItems[i].classList.remove('fixed-card-widget');
}
}
//移除退出蒙版
var quitBox = document.getElementById('quit-box');
if (quitBox) quitBox.remove();
}
// 常规先初始化,确保切换页面后不会有固定卡片留存
RemoveFixedCardWidget()


新建mobileReadingModeHideSidebar.js

路径:[Blogroot]\source\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
// 获取要观察的目标元素
const targetNode = document.body;

// 创建一个 Mutation Observer 实例并指定回调函数
const observer = new MutationObserver((mutationsList) => {
for (const mutation of mutationsList) {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
const updatedBodyClassNames = mutation.target.className;
const target = document.querySelector('#fixedcard-dashboard');

if (!target) {
return; // 如果找不到目标元素,直接返回
}

const isMobileDevice = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);

if (isMobileDevice) {
const shouldHide = updatedBodyClassNames.includes('read-mode');

target.style.display = shouldHide ? 'none' : 'block';

if (shouldHide) {
console.log(1111);
target.style.setProperty('display', 'none', 'important');
}
} else {
console.log('设备不在移动端');
}

// 在这里执行你希望进行的操作
}
}
});

// 配置观察选项(监视属性变化)
const config = { attributes: true };

// 开始观察目标节点
observer.observe(targetNode, config);


新建fixed_card_widget.styl

路径:[Blogroot]\themes\butterfly\source\css\_layout\

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
// 垂直居中卡片样式(排除toc目录卡片)
.fixed-card-widget
&:not(#card-toc)
visibility visible!important
display block!important
position fixed!important
bottom 0
left 0
top 0
right 0
margin auto
margin-bottom auto!important
margin-top auto!important
max-width 300px
max-height 500px
width auto
height auto
overflow-y: scroll
z-index 999
animation rotateX 0.5s ease
animation-fill-mode forwards
&::-webkit-scrollbar
width: 0
// 针对说说卡片做样式兼容适配
.card-shuo
&.fixed-card-widget
#artitalk_main
max-height 460px
overflow scroll
&::-webkit-scrollbar
display: none
#operare_artitalk
.c2
z-index 1000
// 针对标签卡片做样式兼容适配
.card-tags
&.fixed-card-widget
.card-tag-cloud
max-height 460px
overflow scroll
&::-webkit-scrollbar
display: none
// 控制手机端可见
@media screen and (max-width: 768px)
div#fixedcard-dashboard
display flex!important
// 侧栏悬浮按钮样式
div#fixedcard-dashboard
position fixed
top 150px
width fit-content
height 40px
opacity 0.3
transition all 0.5s
display none
background rgba(255,255,255,0.9)
padding 5px 10px
border-top-right-radius 20px
border-bottom-right-radius 20px
z-index 1000
&:hover
opacity 1
button
&.fixedcard-activebtn
width 30px
opacity 1
pointer-events all
// 按钮样式
button
&.fixedcard-activebtn
width 0px
height 30px
transition all .5s
display flex
opacity 0
align-items center
justify-content space-around
pointer-events none
color #757273
// 悬浮按钮头像
.fixedcard-user-avatar
display inline-block
img
&.fixedcard-user-avatar-img
width 30px
height 30px
border-radius 50%
// 悬浮按钮夜间模式适配
[data-theme="dark"]
div#fixedcard-dashboard
background rgba(55,55,55,0.9)
button
&.fixedcard-activebtn
color #bcbdbd

// 卡片开启动画效果
@keyframes rotateX
from
transform rotateX(90deg)
to
transform rotateX(0deg)
// 退出蒙版效果
div#quit-box
position fixed
display block
left 0
top 0
width 100vh
height 100vh
z-index 99
background rgba(25,25,25,0.3)


[data-theme="dark"]
div#quit-box
background rgba(147, 146, 128, 0.3)


新建fixed_card_widget.pug

路径:[Blogroot]\themes\butterfly\layout\includes\custom\

以后的源码魔改教程都会尽量将改动文件归纳到带custom字样的文件夹里,便于管理魔改文件

1
2
3
4
5
6
7
8
9
10
11
#fixedcard-dashboard
if is_post()
each poitem in theme.fixed_card_widget.post
button.fixedcard-activebtn(type="button" title=poitem.title onclick=`FixedCardWidget("` + poitem.type + `","` + poitem.name + `","` + poitem.index + `")`)
i(class=poitem.icon)
else
each paitem in theme.fixed_card_widget.page
button.fixedcard-activebtn(type="button" title=paitem.title onclick=`FixedCardWidget("` + paitem.type + `","` + paitem.name + `","` + paitem.index + `")`)
i(class=paitem.icon)
.fixedcard-user-avatar.fixedcard-activebtn(onclick="RemoveFixedCardWidget()")
img.fixedcard-user-avatar-img(src=url_for(theme.avatar.img) title=config.author)


修改additional-js.pug

路径:[Blogroot]\themes\butterfly\layout\includes\

直接加在文件末尾即可,但是注意缩进!

1
2
3
4
  if theme.busuanzi.site_uv || theme.busuanzi.site_pv || theme.busuanzi.page_pv
script(async data-pjax src=url_for(theme.CDN.busuanzi))
+ if !theme.aside.mobile && theme.fixed_card_widget.enable
+ include ./custom/fixed_card_widget.pug

因为还做了page和post页面不同悬浮按钮的配置,为了让它能够自动切换而不是惰性加载,需要修改[Blogroot]\themes\butterfly\layout\includes\third-party\pjax.pug大约第十四行的位置,在pjax选择器中加入悬浮按钮的id。

1
2
3
4
5
6
7
8
9
10
  script.
let pjaxSelectors = [
'title',
'#config-diff',
'#body-wrap',
'#rightside-config-hide',
'#rightside-config-show',
+ "#fixedcard-dashboard",
'.js-pjax'
]


修改_config.butterfly.yml

新增配置项,此处的选择器其实就是提取了document.getElementsByClassName("name")[index]document.getElementById("name")这两个方法中的参数来确保能够找到侧栏卡片。原本其实是可以做成自动根据侧栏生成的,但是考虑到还有插件挂载和自定义卡片,以及还有部分用户会刻意隐藏一些侧栏卡片,所以干脆还是让用户自己去配置想要加到菜单的卡片好了。
找id或者class的办法很简单,用F12开启控制台,用左上角的元素选择器点选想要的侧栏卡片,在源码栏找到对应的class或者id。因为class是可以重名的,所以还存在一个序列问题,从0开始计数。此处为了避免语意混乱,建议还是用特征明显的class或者id来选择对应卡片。

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
#侧栏悬浮卡片控制按钮
#https://akilar.top/posts/451ac5f8/
fixed_card_widget:
enable: true
page: #页面显示按钮
- type: class #侧栏卡片选择器类型
name: card-info #侧栏卡片选择器名称
index: 0 #侧栏卡片选择器序列
icon: fas fa-address-book #图标
title: 用户信息 #悬停显示提示
- type: class
name: card-clock
index: 0
icon: fas fa-cloud-sun
title: 电子钟
- type: class
name: card-history
index: 0
icon: fas fa-calendar
title: 那年今日
- type: class
name: card-visitor
index: 0
icon: fas fa-earth-americas
title: 来访者
- type: class
name: card-recent-post
index: 0
icon: fas fa-history
title: 最新文章
- type: id
name: card-newest-comments
index: 0
icon: fas fa-comment-dots
title: 最新评论
- type: class
name: card-tags
index: 0
icon: fas fa-tags
title: 标签
- type: class
name: card-categories
index: 0
icon: fas fa-table-list
title: 分类
post: #文章页显示按钮
- type: class
name: card-info
index: 0
icon: fas fa-address-book
title: 用户信息
- type: class
name: card-recent-post
index: 0
icon: fas fa-history
title: 最新文章
- type: class
name: card-visitor
index: 0
icon: fas fa-earth-americas
title: 来访者

inject配置项

1
2
3
4
5
6
  inject:
head:

bottom:
+ - <script data-pjax defer src="/js/hideAsideOnMobile.js"></script>
+ - <script src="/js/mobileReadingModeHideSidebar.js" async></script>

关闭手机端显示侧栏卡片才能启用fixed卡片样式

1
2
3
4
5
6
7
  aside:
enable: true
hide: false
button: true
- mobile: true # display on mobile
+ mobile: false # display on mobile
position: right # left or right