点击查看更新记录

更新记录

2021-07-30:UI实现

  1. 初步实现翻转功能
  2. 布局内容敲定
  3. 正面显示纯文本或图片元素,如头像、描述
  4. 背面显示可点击元素,如站点文章分类标签、自定义按钮、社交图标

2021-08-02:魔改方案实现

  1. 重构PUG文件。为了确保可移值性,弃用大部分原pug内的类名
  2. 精简冗余样式表。
  3. 新增夜间模式适配
  4. 将文章标签分类改为EXP\HP\MP的形式
  5. 重新排布元素布局
  6. 添加了不同分辨率下的样式修复补丁
  7. 不再更改card_author.pug,直接另写一个。确保可移值性
点击查看参考教程
参考方向教程原贴
参考了翻转面板的纯CSS实现方法Parallax Flipping Cards
样式风格参考,图标、音效资源采集SAO Utils
CSS transform 属性CSS transform 属性

写在最前

店长的碎碎念

这是SAO UI PLAN 的第五弹了,效果没有我想的那么理想。在面积有限的作者卡片上做文章实在是有些捉襟见肘,除了可以在配色上动动脑筋以外,没啥可以放内容的地方。

然后就想到了翻转卡片。一下子就把面积增加了一倍。然后求助与万能的codepen,果然不负众望。让我找到了Parallax Flipping Cards这个项目。而且这个项目是纯css实现,且dom存在很明显的重复结构。很适合拿来写成外挂标签或者友链卡片。这部分内容就暂时待定了。啥时候等我找到合适的相册魔改原型再一起编写好了。

其实早在今年六月份的时候就想对侧栏动手了,但是工作忙,周末懒,一直没心思去开始。七月份外公因为窒息休克进了ICU,又因为疫情迟迟不能回去,心情一直处在紧绷状态。好在写这个项目的前一天,外公已经从ICU转普通病房了。

这次的作者卡片魔改依然是存在插件化可行性的。且因为是完全重写了结构。所以不再在原有pug上动刀。而是直接另写一个新pug。

这次我复用了card_author.pug中的所有变量。所以原本有的信息都会有。不用再加任何新的配置项。

魔改步骤

  1. 新建[Blogroot]\themes\butterfly\layout\includes\custom\SAO_card_player.pug,以后的教程中,如非必要,pug文件将不会再沿用_layout之类的主题逻辑分类。全部魔改文件和路径都会放在新建的带custom字样的文件夹中 。此处为了便于后续npm插件化,没有另写辅助函数来处理血条计算。而是直接在pug中计算。
    if theme.aside.card_author.enable
    .card-widget.card-info
    .cols
    .col
    .container
    .front.avatarPanel
    .inner
    .player-title= 'Attributes'
    .player-avatar
    img(src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt="avatar")
    .back.attributesPanel
    .inner
    - var playerLV = Math.ceil(Number( site.posts.length) / 10)
    .player-lv= 'LV.' +playerLV
    .player-name= config.author
    .attributes-value
    if site.posts.length
    .attributes-value-item
    a(href=url_for(config.archive_dir) + '/')
    .attributes= _p('aside.articles')
    .value-bar
    - var fillMAX = Math.ceil(Number( site.posts.length) / 100) * 100
    - var fillNow = Number(site.posts.length)
    - var valueFill = ( fillNow / fillMAX * 100 ).toFixed(2) + '%'
    .value-bar-fill(style=`width:`+ valueFill)
    .value-bar-fill-in(style='background: rgba(89, 230, 54,0.6)')
    span= fillNow +'/'+ fillMAX

    if site.tags.length
    .attributes-value-item
    a(href=url_for(config.tag_dir) + '/')
    .attributes= _p('aside.tags')
    .value-bar
    - var fillMAX = Math.ceil(Number( site.tags.length) / 100) * 100
    - var fillNow = Number(site.tags.length)
    - var valueFill = ( fillNow / fillMAX * 100 ).toFixed(2) + '%'
    .value-bar-fill(style=`width:`+ valueFill)
    .value-bar-fill-in(style='background: rgba(224, 20, 20, 0.6)')
    span= fillNow +'/'+ fillMAX

    if site.categories.length
    .attributes-value-item
    a(href=url_for(config.category_dir) + '/')
    .attributes= _p('aside.categories')
    .value-bar
    - var fillMAX = Math.ceil(Number( site.categories.length) / 100) * 100
    - var fillNow = Number(site.categories.length)
    - var valueFill = ( fillNow / fillMAX * 100 ).toFixed(2) + '%'
    .value-bar-fill(style=`width:`+ valueFill)
    .value-bar-fill-in(style='background: rgba(30, 97, 226, 0.6)')
    span= fillNow +'/'+ fillMAX
    .col
    .container
    .front.descriptionPanel
    .inner
    .player_description!= theme.aside.card_author.description || config.description
    .play-bottom
    .back.buttonPanel
    .inner
    if theme.aside.card_author.button.enable
    a#card-info-btn.button--animated(href=theme.aside.card_author.button.link)
    i(class=theme.aside.card_author.button.icon)
    span=theme.aside.card_author.button.text
    if(theme.social)
    .card-info-social-icons.is-center
    !=fragment_cache('social', function(){return partial('includes/header/social')})
    .play-bottom
  2. 新建[Blogroot]\themes\butterfly\source\css\_layout\SAO_card_player.styl
    @font-face
    font-family: 'SAOUI'
    src: url('https://cdn.jsdelivr.net/npm/akilar-candyassets/fonts/SAOUI.ttf')
    font-display: swap
    .card-widget.card-info
    padding: 0!important
    margin-bottom: 20px;
    font-family: 'SAOUI','ZhuZiAYuanJWD'
    .player_description
    font-size: 20px;
    .card-info-social-icons.is-center
    // 样式错位修复关键帧
    height: 50%;
    .social-icon
    font-size: 1em!important;
    #card-info-btn
    width 90% !important
    font-size 20px !important
    margin 10px 5% !important
    .player-avatar
    display: inline-block;
    width: 5em
    height: 5em
    .play-bottom
    font-size: 20px;
    background: rgba(240, 240, 238,0.9);
    // 样式错位修复关键帧
    height: 40px;
    color rgba(60, 60, 61,0.7)
    text-shadow 1px 1px 1px #888888
    box-shadow: 2px -2px 10px #888888
    .player-lv,
    .player-title
    font-size: 20px;
    background: rgba(240, 240, 238,0.9);
    height: 40px;
    color rgba(60, 60, 61,0.7)
    text-shadow 1px 1px 1px #888888
    box-shadow: 2px 2px 10px #888888
    .player-name
    font-size: 30px
    height: 30px
    color rgba(60, 60, 61,0.7)
    text-shadow 1px 1px 1px #888888
    .attributes-value
    display: block;
    font-size: 20px
    height: auto
    text-align: left
    // 样式错位修复关键帧
    margin: 5% 5%
    a
    color rgba(60, 60, 61,0.7)
    text-shadow 1px 1px 1px #888888
    &:hover
    color: rgba(237, 166, 12,0.8)
    .attributes-value-item
    display: block
    height: 1.5em
    .attributes
    display: inline-block
    width: 20%
    .value-bar
    display: inline-block
    width: 50%
    background: rgba(255, 255, 255, 0.8);
    height: 12px
    margin: 0 3%
    border-radius: 5px
    box-shadow 2px 2px 3px #fff
    border 1px solid rgba(255,255,255,0.5)
    overflow: hidden
    .value-bar-fill
    height: 10px
    margin: 1px 0;
    .value-bar-fill-in
    height: 12px
    span
    font-size: 14px
    .container
    -webkit-transform-style preserve-3d
    transform-style preserve-3d
    -webkit-perspective 1000px
    perspective 1000px
    min-height 200px
    width 100%
    height 50%
    .back
    -webkit-transform rotateY(180deg)
    transform rotateY(180deg)
    -webkit-transform-style preserve-3d
    transform-style preserve-3d
    .front
    -webkit-transform rotateY(0deg)
    transform rotateY(0deg)
    -webkit-transform-style preserve-3d
    transform-style preserve-3d
    &:hover
    .back
    -webkit-transform rotateY(0deg)
    transform rotateY(0deg)
    -webkit-transform-style preserve-3d
    transform-style preserve-3d
    .front
    -webkit-transform rotateY(-180deg)
    transform rotateY(-180deg)
    -webkit-transform-style preserve-3d
    transform-style preserve-3d

    .front,
    .back
    -webkit-transition -webkit-transform .7s cubic-bezier(0.4, 0.2, 0.2, 1)
    transition -webkit-transform .7s cubic-bezier(0.4, 0.2, 0.2, 1)
    -o-transition transform .7s cubic-bezier(0.4, 0.2, 0.2, 1)
    transition transform .7s cubic-bezier(0.4, 0.2, 0.2, 1)
    transition transform .7s cubic-bezier(0.4, 0.2, 0.2, 1), -webkit-transform .7s cubic-bezier(0.4, 0.2, 0.2, 1)
    -webkit-backface-visibility hidden
    backface-visibility hidden
    text-align center
    min-height 200px
    width 100%
    height 50%
    font-size 1.5rem

    .back

    position absolute
    top 0
    left 0
    width 100%

    .front
    &:after
    min-height 200px
    width 100%
    height 50%
    position absolute
    top 0
    left 0
    z-index 1
    width 100%
    height 100%
    content ''
    display block
    opacity .6
    -webkit-backface-visibility hidden
    backface-visibility hidden
    .container:hover .front,
    .container:hover .back
    min-height 200px
    width 100%
    height 50%
    -webkit-transition -webkit-transform .7s cubic-bezier(0.4, 0.2, 0.2, 1)
    transition -webkit-transform .7s cubic-bezier(0.4, 0.2, 0.2, 1)
    -o-transition transform .7s cubic-bezier(0.4, 0.2, 0.2, 1)
    transition transform .7s cubic-bezier(0.4, 0.2, 0.2, 1)
    transition transform .7s cubic-bezier(0.4, 0.2, 0.2, 1), -webkit-transform .7s cubic-bezier(0.4, 0.2, 0.2, 1)

    .inner
    background: rgb(220, 220, 221)
    min-height 200px
    height 50%
    -webkit-transform translateY(-50%) translateZ(60px) scale(0.94)
    transform translateY(-50%) translateZ(60px) scale(0.94)
    top 50%
    position absolute
    left 0
    width 100%
    padding 0
    -webkit-box-sizing border-box
    box-sizing border-box
    outline 1px solid transparent
    -webkit-perspective inherit
    perspective inherit
    z-index 2
    // 不同分辨率下的格式排布
    @media screen and (max-width: 64rem)
    .col
    width calc(33.333333% - 2rem)

    @media screen and (max-width: 48rem)
    .col
    width calc(50% - 2rem)

    @media screen and (max-width: 32rem)
    .col
    width 100%
    // 夜间模式适配
    [data-theme="dark"]
    .card-widget.card-info
    .play-bottom
    background: rgba(25, 25, 21,0.9);
    color rgba(215, 215, 215,0.7)
    text-shadow 1px 1px 1px rgba(38, 230, 242, 0.5)
    box-shadow: 2px -2px 10px rgba(38, 230, 242, 0.5)
    .player-lv,
    .player-title
    background: rgba(25, 25, 21,0.9);
    color rgba(215, 215, 215,0.7)
    text-shadow 1px 1px 1px rgba(38, 230, 242, 0.5)
    box-shadow: 2px 2px 10px rgba(38, 230, 242, 0.5)
    .player-name
    color rgba(215, 215, 215,0.7)
    text-shadow 1px 1px 1px rgba(38, 230, 242, 0.5)
    .attributes-value
    a
    color rgba(215, 215, 215,0.7)
    text-shadow 1px 1px 1px rgba(38, 230, 242, 0.5)
    &:hover
    color: rgb(237, 166, 12)
    .attributes-value-item
    .value-bar
    background: rgba(25, 25, 21,0.9);
    box-shadow 2px 2px 3px rgba(38, 230, 242, 0.5)
    border 1px solid rgba(25, 25, 21,0.9)
    .inner
    background: rgba(25, 25, 21,0.9)

  3. 因为这次不是对card_author.pug动刀子,所以要再改下路径。以后若是插件化的话,会直接挂载,那时候就是到配置文件中关闭card_author了。修改[Blogroot]\themes\butterfly\layout\includes\widget\index.pug,视主题版本不同,index.pug的格式也不尽相同。好在这次我们只是需要改文件路径。不论是什么版本的主题,都只需在文件中搜索widget/card_author,将其替换为custom/SAO_card_player即可。

    可能出现的bug

    因为这次正反面是用的伪类实现。我实在是不知道怎么用flex布局来调整它。所以还是很没出息的用的盒子布局。所以在描述、按钮、社交图标的内容不同时,会出现很多的自适应问题。
    已经在stylus文件中注释了样式修复的几处关键帧,若出现错位,可以自己调整参数。

    TO DO

    重写作者卡片UI,改成游戏角色属性面板

    常规显示头像,鼠标悬停翻转显示人物属性卡片

    常规显示站点描述,鼠标悬停翻转显示social icon

    点击头像,持续显示站点描述(废案)