点击查看更新记录

更新记录

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,调整布局。
      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哦。
    // 电脑端悬停按钮样式
    #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的作用就是提供滚动监测了,这里因为翻页按钮是常态隐藏的,所以没有使用它来作为监测元素,我这里是使用评论区部分作为监测元素,即出现评论区了才显示换页按钮。
    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就大功告成啦。
    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风格弹窗。
      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