点击查看更新记录

更新记录

2022-03-24:内容订正,新增彩蛋

  1. 订正了两处错误,diff代码块缺失.pagination-card新增标识。
  2. 调整了手机端按钮高度的权值,以兼容未做copyright卡片魔改的用户。
  3. 新增与SAO UI PLAN Notify的教程联动。

2022-03-16:基本功能逻辑实现

  1. 编写了电脑端的悬停卡片样式,且左右分离

2022-03-15:基本功能逻辑实现

  1. 实现了UI分离
  2. 编写了手机端和电脑端的按钮样式
  3. 编写了手机端的悬停卡片样式
点击查看参考教程
参考方向教程原贴
参考了事件监听动作的语法addEventListener
监听dom元素是否在屏幕内的示例JS判断指定dom元素是否在屏幕内的方法实例

思路分析

我试图通过将文章底部的按钮改至左右两侧,类似翻页键,同时添加悬停动作,通过css对兄弟相邻元素的hover监测来控制显隐,悬停按钮时在页面正中显示对应文章卡片。

首先要解决的是按钮显示问题,如果是常显,有可能遮盖正文内容,尤其是手机端应该不会有足够的位置。所以尝试通过设置滚动事件监听,在页面滚动至原本上下页翻页的位置,也就是正文刚好读完的时候,才显示按钮。虽然会遮盖一部分评论,不过可以把按钮调整到正中,手机端调扁一点,毕竟不是正文的话,也不用太纠结遮盖问题。

然后就是文章卡片的参数取值问题,这部分可以沿用Blogroot\themes\butterfly\layout\includes\pagination.pug里的变量逻辑,这样就可以把问题局限在对UI的调整上。毕竟butterfly目前的上下篇很贴心的提供了封面,标题这两个元素。

至于卡片样式,虽然我一开始是想做成手机端侧栏卡片fixed样式那种风格,但是考虑到可用的可见参数其实也就封面和标题,还要顾及到手机端的显示情况,所以目前的打算是做成书签风格。一个圆角头像放封面,和一个矩形拼接放标题。布局上是打算电脑端做成横向排列,手机端做成纵向排列的。

魔改步骤


  1. 修改[Blogroot]\themes\butterfly\layout\includes\pagination.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
      if is_post()
    - let prev = theme.post_pagination === 1 ? page.prev : page.next
    - let next = theme.post_pagination === 1 ? page.next : page.prev
    nav#pagination.pagination-post
    if(prev)
    - var hasPageNext = next ? 'pull-left' : 'pull-full'
    .prev-post(class=hasPageNext)
    - var pagination_cover = prev.cover === false ? prev.randomcover : prev.cover
    - a(href=url_for(prev.path))
    + a(href=url_for(prev.path) title=prev.title )
    + i.fas.fa-chevron-left.prev-icon
    + .prev-label=_p('pagination.prev')
    + .pagination-card
    img.prev-cover(src=url_for(pagination_cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` alt='cover of previous post')
    .pagination-info
    .label=_p('pagination.prev')
    .prev_info=prev.title

    if(next)
    - var hasPagePrev = prev ? 'pull-right' : 'pull-full'
    - var pagination_cover = next.cover == false ? next.randomcover : next.cover
    .next-post(class=hasPagePrev)
    - a(href=url_for(next.path))
    + a(href=url_for(next.path) title=next.title )
    + i.fas.fa-chevron-right.next-icon
    + .next-label=_p('pagination.next')
    + .pagination-card
    img.next-cover(src=url_for(pagination_cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` alt='cover of next post')
    .pagination-info
    .label=_p('pagination.next')
    .next_info=next.title
  2. 新建[Blogroot]\themes\butterfly\source\css\_layout\fixed-pagination.styl,为了区分左右和PC端,手机端,我可是头一次这么卖力的写了三份UI哦。
    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
    // 电脑端悬停按钮样式
    #pagination
    .prev-post a,
    .next-post a
    z-index 99
    display flex!important
    overflow hidden
    height 150px
    position fixed!important
    top 45%
    background rgba(0,0,0,0.6)
    width 65px
    font-size 65px
    align-content space-around
    color white
    border-radius 10px
    align-items center
    justify-content space-around

    .prev-post .prev-label,
    .next-post .next-label
    display none
    .prev-post
    a
    left 45px
    .next-post
    a
    right 45px
    // 电脑端悬停卡片样式
    @media screen and (min-width: 768px)
    #pagination
    .pagination-card
    z-index 99
    display none
    position fixed
    top 0
    left 0
    right 0
    bottom 0
    margin auto
    height 150px
    width 400px
    background rgba(66 , 66, 66, 0.9)
    img
    z-index 100
    position absolute
    width 120px!important
    height 120px!important
    top 15px!important
    opacity 0.9!important
    border-radius 50%
    .pagination-info
    position absolute
    padding 0 0 0!important
    top 0px
    width calc( 100% - 150px )
    height 200px
    display flex
    flex-direction column
    transform unset!important
    .prev_info,
    .next_info
    width 100%
    height 75px
    display flex
    flex-direction column
    align-items center
    justify-content space-around
    .label
    width 100%
    height 75px
    display flex
    flex-direction column
    align-items center
    justify-content space-around
    &::before
    content ""
    width 90%
    height 2px
    top 40%
    background white
    position absolute
    .prev-post
    .pagination-card
    flex-direction column
    align-items center
    border-top-left-radius 75px
    border-top-right-radius 10px
    border-bottom-left-radius 75px
    border-bottom-right-radius 10px
    img
    left 15px!important
    .pagination-info
    left 150px

    .next-post
    .pagination-card
    flex-direction column
    align-items center
    border-top-left-radius 10px
    border-top-right-radius 75px
    border-bottom-left-radius 10px
    border-bottom-right-radius 75px
    img
    right 15px!important
    .pagination-info
    right 150px

    // 手机端样式
    @media screen and (max-width: 768px)
    #pagination
    .prev-post
    a
    height 45px !important
    width 100px
    top 35%
    font-size 20px
    border-radius 10px
    padding 5px
    left 0px
    border-top-left-radius 0px
    border-top-right-radius 22.5px
    border-bottom-left-radius 0px
    border-bottom-right-radius 22.5px
    i
    &::before
    content "\f101"
    .prev-label
    display inline-block
    font-size 20px
    float left
    margin-right 5px

    .next-post
    a
    height 45px !important
    width 100px
    top 35%
    font-size 20px
    border-radius 10px
    padding 5px
    right 0px
    border-top-left-radius 22.5px
    border-top-right-radius 0px
    border-bottom-left-radius 22.5px
    border-bottom-right-radius 0px
    i
    &::before
    content "\f100"
    .next-label
    display inline-block
    font-size 20px
    float right
    margin-left 5px
    .pagination-card
    z-index 99
    display none
    position fixed
    top 0
    left 0
    right 0
    bottom 0
    margin auto
    height 300px
    width 90px
    background rgba(66 , 66, 66, 0.9)
    flex-direction column
    align-items center
    border-radius 10px
    border-top-left-radius 45px
    border-top-right-radius 45px
    border-bottom-left-radius 10px
    border-bottom-right-radius 10px
    img
    z-index 100
    position absolute
    width 70px!important
    height 70px!important
    top 10px!important
    opacity 0.9!important
    border-radius 50%
    .pagination-info
    position absolute
    padding 0 0 0!important
    top 90px
    width 100%
    height 200px
    display flex
    flex-direction row
    justify-content flex-end
    transform unset!important
    .prev_info,
    .next_info
    width 60%!important
    height 200px
    display block
    writing-mode vertical-rl
    text-align center
    .label
    width 40%
    writing-mode vertical-rl
    text-align start
    &::before
    content ""
    width 2px
    height 180px
    background white
    position absolute
    // 夜间模式配色
    [data-theme="dark"]
    #pagination
    .prev-post a,
    .next-post a
    background rgba(255,255,255,0.3)
    color rgba(20, 20, 20,0.8)
    // 悬停显示卡片动作
    #pagination
    .prev-post,
    .next-post
    a
    &:hover
    & + .pagination-card
    display flex
  3. 新建[Blogroot]\themes\butterfly\source\js\fixed-pagination.js,这个js的作用就是提供滚动监测了,这里因为翻页按钮是常态隐藏的,所以没有使用它来作为监测元素,我这里是使用评论区部分作为监测元素,即出现评论区了才显示换页按钮。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    document.addEventListener('scroll',function(){

    //滚动条高度+视窗高度 = 可见区域底部高度
    var visibleBottom = window.scrollY + document.documentElement.clientHeight;
    //可见区域顶部高度
    var visibleTop = window.scrollY;
    // 获取翻页按钮容器
    var pagination = document.getElementById('pagination');
    // 获取位置监测容器,此处采用评论区
    var eventlistner = document.getElementById('post-comment');
    if (eventlistner&&pagination){
    var centerY = eventlistner.offsetTop+(eventlistner.offsetHeight/2);
    if(centerY>visibleTop&&centerY<visibleBottom){
    pagination.style.display = 'flex';
    }else{
    pagination.style.display = 'none';
    }
    }
    })
  4. [Blogroot]\_config.butterfly.yml的inject配置项引入js就大功告成啦。
    1
    2
    3
    4
    inject:
    head:
    bottom:
    - <script src="/js/fixed-pagination.js" async></script>

教程联动

若配置了SAO-UI-PLAN-Notify,则可以这样改动pagination.pug,将页面跳转换成SAO风格弹窗:

  1. 修改[Blogroot]\themes\butterfly\layout\includes\pagination.pug,将页面跳转换成SAO风格弹窗。
    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
      if is_post()
    - let prev = theme.post_pagination === 1 ? page.prev : page.next
    - let next = theme.post_pagination === 1 ? page.next : page.prev
    nav#pagination.pagination-post
    if(prev)
    - var hasPageNext = next ? 'pull-left' : 'pull-full'
    .prev-post(class=hasPageNext)
    - var pagination_cover = prev.cover === false ? prev.randomcover : prev.cover
    - a(href=url_for(prev.path))
    + a(href='javascript:void(0);' onclick=`SAONotify("Prev Post","是否跳转至上一篇:<br>${prev.title}","pjax.loadUrl('/${prev.path}')")` title=prev.title )
    + i.fas.fa-chevron-left.prev-icon
    + .prev-label=_p('pagination.prev')
    + .pagination-card
    img.prev-cover(src=url_for(pagination_cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` alt='cover of previous post')
    .pagination-info
    .label=_p('pagination.prev')
    .prev_info=prev.title

    if(next)
    - var hasPagePrev = prev ? 'pull-right' : 'pull-full'
    - var pagination_cover = next.cover == false ? next.randomcover : next.cover
    .next-post(class=hasPagePrev)
    - a(href=url_for(next.path))
    + a(href='javascript:void(0);' onclick=`SAONotify("Next Post","是否跳转至下一篇:<br>${next.title}","pjax.loadUrl('/${next.path}')")` title=next.title )
    + i.fas.fa-chevron-right.next-icon
    + .next-label=_p('pagination.next')
    + .pagination-card
    img.next-cover(src=url_for(pagination_cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` alt='cover of next post')
    .pagination-info
    .label=_p('pagination.next')
    .next_info=next.title