hexo 文章中代码模块添加展开收起效果

作为程序员的博客网站,代码占据主要部分,但是一篇文章代码显示过多会显得文章冗长,作为极简主义,必须要给代码添加展开收起效果。

逻辑说明

本操作由 jQuery 选择器选择代码模块,给超过某个高度的代码模块添加展开收起的盒子,让盒子实现展开隐藏效果。

问题

由于是由 jQuery 实现的效果,页面在加载进来之后,代码模块高度会有闪烁问题。

原因:因为是浏览器端执行的效果,会等到 JS 加载完了之后才会执行,所以页面载入会首先显示默认高度,等到 JS 计算完之后再显示隐藏之后的高度。

具体效果参考本站的代码模块。

可以用 hexotag 插件来规避以上问题,但是由于站点代码模块比较多,如果一个个代码模块去加 tag 标签,想死的心都有了。所以就这样了…

步骤

  1. 添加文件 themes/landscape/source/js/code-unfold.js

注意本文的 ES6 语法,参考文章 hexo 静态资源 js 文件添加 es6 语法支持

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
const CODE_MAX_HEIGHT = 200;
const containers = [];

// 展开
$('body').on('click', '.js_unfold_code_btn', function () {
$(this).closest('.js_highlight_container').addClass('on');
});
// 收起
$('body').on('click', '.js_retract_code_btn', function () {
const $container = $(this).closest('.js_highlight_container').removeClass('on');
const winTop = $(window).scrollTop();
const offsetTop = $container.offset().top;
$(this).css('top', 0);
if (winTop > offsetTop) {
// 设置滚动条位置
$('body, html').animate({
scrollTop: $container.offset().top - CODE_MAX_HEIGHT
}, 600);
}
});
// 滚动事件,触发动画效果
$(window).on('scroll', function () {
const scrollTop = $(window).scrollTop();
const temp = [];
for (let i = 0; i < containers.length; i++) {
const item = containers[i];
const { $container, height, $hide, hasHorizontalScrollbar } = item;
if ($container.closest('body').length === 0) {
// 如果 $container 元素已经不在页面上, 则删除该元素
// 防止pjax页面跳转之后,元素未删除
continue;
}
temp.push(item);
if (!$container.hasClass('on')) {
continue;
}
const offsetTop = $container.offset().top;
const hideBtnHeight = $hide.outerHeight();
// 减去按钮高度,减去底部滚动条高度
const maxTop = parseInt(height - (hasHorizontalScrollbar ? 17 : 0) - hideBtnHeight);
let top = parseInt(
Math.min(
Math.max(scrollTop - offsetTop, 0), // 如果小于 0 ,则取 0
maxTop,// 如果大于 height ,则取 height
)
);
// 根据 sin 曲线设置"收起代码"位置
const halfHeight = parseInt($(window).height() / 2 * Math.sin((top / maxTop) * 90 * (2 * Math.PI/360)));
$hide.css('top', Math.min(top + halfHeight, maxTop));
}
containers = temp;
});

// 添加隐藏容器
const addCodeWrap = ($node) => {
const $container = $node.wrap('<div class="js_highlight_container highlight-container"><div class="highlight-wrap"></div></div>').closest('.js_highlight_container');

// 底部 "展开代码" 与 侧边栏 "收起代码"
const $btn = $(`
<div class="highlight-footer">
<a class="js_unfold_code_btn show-btn" href="javascript:;">展开代码<i class="fa fa-angle-down" aria-hidden="true"></i></a>
</div>
<a class="js_retract_code_btn hide-btn" href="javascript:;"><i class="fa fa-angle-up" aria-hidden="true"></i>收起代码</a>
`);

$container.append($btn);
return $container;
};

const ret = () => {
$('.highlight').each(function () {
// 防止重复渲染
if (this.__render__ === true) {
return true;
}
this.__render__ = true;
const $this = $(this);
const height = $(this).outerHeight();
if (height > CODE_MAX_HEIGHT) {
// 添加展开&收起容器
const $container = addCodeWrap($this, height);
containers.push({
$container,
height,
$hide: $container.find('.js_retract_code_btn'),
hasHorizontalScrollbar: this.scrollWidth > this.offsetWidth,
});
}
});
};

export default ret;
  1. 引入js并执行,修改文件 themes/landscape/source/js/search.js
1
2
+ import codeUnfold from './code-unfold';
+ codeUnfold();
  1. 添加样式,修改文件 themes/landscape/source/css/_partial/highlight.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
    // 展开收起效果
    .highlight-container
    position: relative
    background-color: highlight-background
    &.on
    .highlight-footer
    display: none
    .hide-btn
    display: flex
    .highlight-wrap
    max-height: none
    .highlight-wrap
    overflow: hidden
    max-height: 200px
    .highlight-footer
    position absolute
    width: 100%
    left: 0
    bottom: 0
    height: 60px
    background-image: 'linear-gradient(-180deg, rgba(255,255,255,0) 0%, %s 65%)' % highlight-background;
    text-align: center
    .show-btn
    color: #fff
    position: absolute
    left: 50%
    transform: translateX(-50%)
    bottom: 0
    line-height: 2.6em
    text-decoration: none
    padding: 0 0.8em
    &:hover
    text-decoration: none
    .hide-btn
    color: #fff
    font-size: 12px
    width: 22px
    position: absolute
    left: -21px
    top: 0
    line-height: 1em
    text-decoration: none
    text-align: center
    display: none
    flex-direction: column
    background-color: highlight-background
    border-radius: 4px 0 0 4px
    padding: 0.1em 0 0.6em
    transition: top ease 0.35s
    &:hover
    text-decoration: none
    .fa-angle-up,
    .fa-angle-down
    font-family: font-icon
    font-style: normal
    color: #ca0c16
    .fa-angle-up:before
    content:"\f106"
    .fa-angle-down:before
    content:"\f107"
    margin-left: 0.5em
  1. 重启项目,查看效果。
本文由 linx(544819896@qq.com) 创作,采用 CC BY 4.0 CN协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。本文链接为: https://blog.jijian.link/2020-02-26/hexo-article-code-add-unfold/

如果您觉得文章不错,可以点击文章中的广告支持一下!