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;
  2. 引入js并执行,修改文件 themes/landscape/source/js/search.js

    1
    2
    + import codeUnfold from './code-unfold';
    + codeUnfold();
  3. 添加样式,修改文件 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
  4. 重启项目,查看效果。

本文由 linx(544819896@qq.com) 创作,采用 CC BY 4.0 CN协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。本文链接为: https://blog.jijian.link/2020-02-26/hexo-article-code-add-unfold/

如果您觉得文章不错,可以请我喝一杯咖啡!