源计划-方舟:首页卡片

2023-01-31 11:20:14 浏览数 (1)

点击查看更新记录

更新记录

2023-01-02:内测版

  1. 源计划-赛博更名为源计划-方舟
  2. 重写首页卡片。
  3. 调整布局,常态仅显示标题和封面。极致简化信息
  4. 悬停标题和封面,弹出描述面板
  5. 宽屏左右张开,窄屏上下张开。
  6. 置顶、评论数、分类、标签均隐藏至卡片四个牙角。悬停展开。

点击查看参考教程

参考方向

教程原贴

参考了UI风格和配色样式

Neon-Space-Rainmeter

参考了UI风格和配色样式

JARVIS-Highpitched-OS

fontawesome图标文档

fontawesome

Flex布局参数解释

Flex 布局教程:语法篇 - 阮一峰的网络日志

Transition属性实现平滑过渡动画

CSS3实现伪类hover离开时平滑过渡效果示例

CSS伪类实现三角形绘制

纯CSS 实现绘制各种三角形(各种角度) - saucxs - 博客园

使用clip-path实现多边形剪裁。

不可思议的CSS之clip-path

站内教程:iconfont引入教程

Hexo引入阿里矢量图标库

预览效果

点击查看预览效果

魔改步骤

本篇需要用到iconfont作为卡片底部的装饰性图标。请先完成前置教程:Hexo引入阿里矢量图标库,务必确保symbol方案能够使用后再进行下方内容。

新建[Blogroot]themesbutterflyscriptshelperscybericon.js,这个js的作用是返回一个随机的图标值,逢年过节的还能换成喜庆点的图标,注意以下icon[]内部的图标均为我个人图标库内的图标名称。请务必记得替换成你自己的图标。且这是个内部函数,必须保证在scripts目录下,不要自作聪明建在别的目录还到inject配置项去引入

代码语言:javascript复制
hexo.extend.helper.register('cybericon', function () {
  var icon = [
      '#icon-fukong',
      '#icon-fan',
      '#icon-partial-discharge',
      '#icon-menu-zizhanbaowei',
      '#icon-YunTai-unfold',
      '#icon-camera-GOTO_PRESET',
      '#icon-d3',
      '#icon-copy',
      '#icon-config'
   ]
  var index = Math.floor(Math.random()*icon.length);
  return icon[index]
});

重写[Blogroot]themesbutterflylayoutincludesmixinspost-ui.pug,将以下内容覆盖到源文件内:

代码语言:javascript复制
mixin postUI(posts)
  each article , index in page.posts.data
    .recent-post-item.cyber-post-card
      -
        let link = article.link || article.path
        let title = article.title || _p('no_title')
        let subtitle = article.subtitle || title
        const position = theme.cover.position
        let leftOrRight = position === 'both'
          ? index%2 == 0 ? 'left' : 'right'
          : position === 'left' ? 'left' : 'right'
        let post_cover = article.cover
        let no_cover = article.cover === false || !theme.cover.index_enable ? 'no-cover' : ''
      -
      //- 更新时间、创建时间
      .recent-post-item-headline
        //- 置顶标签
        if (is_home() && (article.top || article.sticky > 0))
          .article-meta-sticky
            i.fas.fa-thumbtack.sticky
            span.sticky= _p('sticky')             
        //- 文章评论数
        mixin countBlockInIndex
          - needLoadCountJs = true
          span.article-meta-comments
            i.fas.fa-comments
            if block
              block
            span.article-meta-label= ' '   _p('card_post_count')
        if theme.comments.card_post_count
          case theme.comments.use[0]
            when 'Disqus'
               countBlockInIndex
                a(href=full_url_for(link)   '#disqus_thread')
                  i.fa-solid.fa-spinner.fa-spin
            when 'Disqusjs'
               countBlockInIndex
                a(href=full_url_for(link)   '#disqusjs')
                  span.disqus-comment-count(data-disqus-url=full_url_for(link))
                    i.fa-solid.fa-spinner.fa-spin
            when 'Valine'
               countBlockInIndex
                a(href=url_for(link)   '#post-comment')
                  span.valine-comment-count(data-xid=url_for(link))
                    i.fa-solid.fa-spinner.fa-spin
            when 'Waline'
               countBlockInIndex
                a(href=url_for(link)   '#post-comment')
                  span.waline-comment-count(id=url_for(link))
                    i.fa-solid.fa-spinner.fa-spin
            when 'Twikoo'
               countBlockInIndex
                a.twikoo-count(href=url_for(link)   '#post-comment')
                  i.fa-solid.fa-spinner.fa-spin
            when 'Facebook Comments'
               countBlockInIndex
                a(href=url_for(link)   '#post-comment')
                  span.fb-comments-count(data-href=urlNoIndex(article.permalink))
            when 'Remark42'
               countBlockInIndex
                a(href=url_for(link)   '#post-comment')
                  span.remark42__counter(data-url=urlNoIndex(article.permalink))
                    i.fa-solid.fa-spinner.fa-spin
            when 'Artalk'
               countBlockInIndex
                a(href=url_for(link)   '#post-comment')
                  span.artalk-count(data-page-key=url_for(link))
                    i.fa-solid.fa-spinner.fa-spin
        if (theme.post_meta.page.date_type)
          if (theme.post_meta.page.date_type === 'both')
            .recent-post-time
              i.fas.fa-history
              span.article-meta-label=_p('post.updated')
              time.post-meta-date-updated(datetime=date_xml(article.updated) title=_p('post.updated')   ' '   full_date(article.updated))=date(article.updated, config.date_format)
          
          //- 仅显示更新或创建时间
          else
            - let data_type_updated = theme.post_meta.page.date_type === 'updated'
            - let date_type = data_type_updated ? 'updated' : 'date'
            - let date_icon = data_type_updated ? 'fas fa-history' :'far fa-calendar-alt'
            - let date_title = data_type_updated ? _p('post.updated') : _p('post.created')
            .recent-post-time
              i(class=date_icon)
              span.article-meta-label=date_title
              time(datetime=date_xml(article[date_type]) title=date_title   ' '   full_date(article[date_type]))=date(article[date_type], config.date_format)
      //- 内容版块
      .recent-post-content(class=leftOrRight)
        //- 封面和标题
        .recent-post-cover
          img.article-cover(src=url_for(post_cover) onerror=`this.onerror=null;this.src='`  url_for(theme.error_img.post_page)   `'` alt=subtitle)
        .recent-post-info
          a.article-title(href=url_for(link) title=subtitle)
            .article-title-link= title
        //- 装饰图标盲盒
        svg.icon.cyber-decoration(aria-hidden="true")
          use(xlink:href=cybericon())
        //- 文章描述
        a.recent-post-description(href=url_for(link) title=subtitle)
          //- Display the article introduction on homepage
          case theme.index_post_content.method
            when false
              - break
            when 1
              .article-content-text!= article.description
            when 2
              if article.description
                .article-content-text!= article.description
              else
                - const content = strip_html(article.content)
                - let expert = content.substring(0, theme.index_post_content.length) 
                - content.length > theme.index_post_content.length ? expert  = ' ...' : ''
                .article-content-text!= expert
            default
              - const content = strip_html(article.content)
              - let expert = content.substring(0, theme.index_post_content.length) 
              - content.length > theme.index_post_content.length ? expert  = ' ...' : ''
              .article-content-text!= expert
      .recent-post-item-bottomline        
        //- 分类项
        if (theme.post_meta.page.categories && article.categories.data.length > 0)
          .article-meta-categories
            each item, index in article.categories.data
              a(href=url_for(item.path)).article-meta__categories #[=item.name]
              if (index < article.categories.data.length - 1)
                i.fas.fa-angle-right.article-meta-link
        //- 标签项
        if (theme.post_meta.page.tags && article.tags.data.length > 0)
          .article-meta-tags
            each item, index in article.tags.data
              a(href=url_for(item.path)).article-meta__tags #[=item.name]
              if (index < article.tags.data.length - 1)
                span.article-meta-link #[='•']
                if (theme.post_meta.page.date_type)
        //- 同时显示更新和创建时间
        if (theme.post_meta.page.date_type === 'both')
          //- 同时显示更新和创建时间
          .recent-post-time
            i.far.fa-calendar-alt
            span.article-meta-label=_p('post.created')
            time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created')   ' '   full_date(article.date))=date(article.date, config.date_format)
    if theme.ad && theme.ad.index
      if (index   1) % 3 == 0
        .recent-post-item.ads-wrap!=theme.ad.index

新建[Blogroot]themesbutterflysourcecss_layoutcyber_index_card.styl,这个stylus写的还挺复杂的,连我都要密密麻麻的注释才能分得清哪个是哪个。配色可以在开头的代码版块里自行调整。过年了嘛我就整了个喜庆点的红色。

代码语言:javascript复制
//default color:
:root
  --cyber-post-item-transition: all 0.5s cubic-bezier(0.59, 0.01, 0.48, 1.17)//动画效果
  --cyber-post-item-border: rgba(153, 54, 44,0.8) //卡片边框颜色
  --cyber-post-item-background: rgba(67, 66, 65,0.8) //背景色
  --cyber-post-item-screen: rgba(61, 146, 204,0.6) //描述卡片背景
  --cyber-post-item-font-color: #fff //字体颜色
  --cyber-post-item-font-hover: #d97f17//文字悬停颜色
  --cyber-post-item-box-shadow: rgba(111, 160, 225,0.8) //边框光晕颜色
  --cyber-post-item-text-shadow: rgba(50, 51, 50,0.7) //字体光晕颜色
[data-theme="dark"]
  --cyber-post-item-border: rgba(55, 112, 143,0.8) //卡片边框颜色
  --cyber-post-item-background: rgba(47, 66, 70,0.8) //背景色
  --cyber-post-item-screen: rgba(61, 146, 204,0.6) //描述卡片背景
  --cyber-post-item-font-color: rgb(233, 233, 233)//字体颜色
  --cyber-post-item-font-hover: #433686//文字悬停颜色
  --cyber-post-item-box-shadow: rgba(252, 252, 252, 0.8) //边框光晕颜色
  --cyber-post-item-text-shadow: rgba(50, 51, 50,0.7) //字体光晕颜色
//顶栏底栏基本属性
cyber_post_item_line()
  display: flex;
  width: 100%;
  height: 40px;
  justify-content: center;
  flex-direction: row;
  align-items: center;
  position: relative
  font-family: 'UnidreamLED','TaikoMagic';
//时间栏
cyber_post_item_time()
  width: fit-content;
  height: 40px;
  background: var(--cyber-post-item-background);
  color: var(--cyber-post-item-font-color);
  padding: 5px 15px;
  font-size: 15px;
  display: flex;
  position: relative;
  z-index: 3;
  align-items: center;
  justify-content: center;
  border: 5px groove var(--cyber-post-item-border);
  transform: skewX(45deg);
  clip-path: polygon(0 50%,35px 5px,50% 5px,50% 0,100% 0,100% 50%,calc(100% - 35px) calc(100% - 5px),50% calc(100% - 5px),50% 100%,0 100%);
  *
    transform: skewX(-45deg);
    margin: 0px 3px
    cyber_post_item_link_hover()
//置顶,评论数,分类,标题等元数据。
cyber_post_item_meta(skewXdeg,reverseskew,insetwidth,borderwidth,borderstyle)
  display: flex;
  position: absolute;
  background: var(--cyber-post-item-background);
  border-color: var(--cyber-post-item-border); 
  font-size: 14px;
  z-index: 3;
  height: 18px;
  line-height: 14px;
  transition: var(--cyber-post-item-transition)
  transform: skewX(skewXdeg);
  clip-path: inset(insetwidth);
  border-width: borderwidth;
  border-style: borderstyle;
  *
    transform: skewX(reverseskew);
    margin: 0px 2px
    color: var(--cyber-post-item-font-color)
    cyber_post_item_link_hover()
  &:hover
    clip-path: inset(0 0 0 0);
    transition: var(--cyber-post-item-transition)
//两侧的异形边框
cyber_post_item_border()
  &::before 
    width: 100%;
    z-index: 3
    height: 100%;
    left: 0;
    top: 0;
    content: ""
    background: var(--cyber-post-item-border)
    position: absolute
    clip-path: polygon(50% 50%, 35px 50%, 30px calc(50% - 5px), 30px 50%, 25px 50%, 25px calc(50% - 25px), 15px calc(50% - 30px), 15px 10px, 30px 0, 10px 0px, 0 10px, 0 calc(100% - 10px), 10px 100%, 30px 100%, 15px calc(100% - 10px), 15px calc(50%   30px),25px calc(50%   25px), 25px 50%, 30px 50%, 30px calc(50%   5px), 35px 50%, 50% 50%, calc(100% - 35px) 50%, calc(100% - 30px) calc(50% - 5px), calc(100% - 30px) 50%, calc(100% - 25px) 50%, calc(100% - 25px) calc(50% - 25px), calc(100% - 15px) calc(50% - 30px), calc(100% - 15px) 10px, calc(100% - 30px) 0, calc(100% - 10px) 0px, 100% 10px, 100% calc(100% - 10px), calc(100% - 10px) 100%, calc(100% - 30px) 100%, calc(100% - 15px) calc(100% - 10px), calc(100% - 15px) calc(50%   30px),calc(100% - 25px) calc(50%   25px), calc(100% - 25px) 50%, calc(100% - 30px) 50%, calc(100% - 30px) calc(50%   5px), calc(100% - 35px) 50%, 50% 50%)
//悬停链接颜色
cyber_post_item_link_hover()
  &:hover
    transition: all 0.3s
    color: var(--cyber-post-item-font-hover)
//封面和标题的基础样式
cyber_post_item_cover_title()
  background: var(--cyber-post-item-background)
  overflow: hidden      
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  z-index: 2
  transition: var(--cyber-post-item-transition)
//左半边切分
cyber_post_item_left_content()
  left: 0
  top: 0
  border-radius: 15px 0 0 15px;
  clip-path: polygon(calc(100% - 80px) 50%, calc(100% - 50px) calc(50% - 30px), 100% calc(50% - 30px), 100% 0, 0 0, 0 100%, 100% 100%, 100% calc(50%   30px), calc(100% - 50px) calc(50%   30px))
//左半边切分悬停
cyber_post_item_left_content_hover()
  clip-path: polygon(0 50%, 10px calc(50% - 5px), 30% calc(50% - 5px), 40% 0, 0 0, 0 100%, 40% 100%, 30% calc(50%   5px), 10px calc(50%   5px))
  transition: var(--cyber-post-item-transition)
//右半边切分
cyber_post_item_right_content()
  right: 0
  top: 0
  border-radius: 0 15px 15px 0;
  clip-path: polygon(80px 50%, 50px calc(50% - 30px), 0 calc(50% - 30px), 0 0, 100% 0, 100% 100%, 0 100%, 0 calc(50%   30px), 50px calc(50%   30px))
//右半边切分悬停
cyber_post_item_right_content_hover()
  clip-path: polygon(100% 50%, calc(100% - 10px) calc(50% - 5px), 70% calc(50% - 5px), 60% 0, 100% 0, 100% 100%, 60% 100%, 70% calc(50%   5px), calc(100% - 10px) calc(50%   5px))
  transition: var(--cyber-post-item-transition)
//上半边切分
cyber_post_item_top_content()
  left: 0
  top: 0
  border-radius: 15px 15px 0 0;
  clip-path: polygon(50% calc(100% - 30px), calc(50% - 30px) calc(100% - 30px), calc(50% - 45px) 100%, 0 100%, 0 0, 100% 0, 100% 100%, calc(50%   45px) 100%, calc(50%   30px) calc(100% - 30px));
//上半边切分悬停
cyber_post_item_top_content_hover()
  clip-path: polygon(30% 30px, 20px 30px, 20px calc(100% - 15px), 0 100%, 0 0, 50% 0, calc(100% - 45px) 0, calc(100% - 60px) 15px, calc(30%   10px) 15px)
  transition: var(--cyber-post-item-transition)
//下半边切分
cyber_post_item_bottom_content()
  left: 0
  bottom: 0
  border-radius: 0 0 15px 15px;
  clip-path: polygon(50% 30px, calc(50% - 30px) 30px, calc(50% - 45px) 0, 0 0, 0 100%, 100% 100%, 100% 0, calc(50%   45px) 0, calc(50%   30px) 30px);
//下半边切分悬停
cyber_post_item_bottom_content_hover()
  clip-path: polygon(70% calc(100% - 30px), calc(100% - 20px) calc(100% - 30px), calc(100% - 20px) 15px, 100% 0, 100% 100%, 50% 100%, 45px 100%, 60px calc(100% - 15px), calc(70% - 10px) calc(100% - 15px))
  transition: var(--cyber-post-item-transition)

//gitcalendar样式临时性
.recent-post-item
  &#gitcalendarBar
    position: relative
    padding: 30px 30px!important;
    background: transparent!important;
    cyber_post_item_border()
    div#git_container
      background: var(--cyber-post-item-background);;
      border-radius: 15px;
// 卡片本体
.recent-post-item
  margin: 30px 0px;
  &.cyber-post-card
    z-index: 0
    display: flex;
    position: relative
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: center;
    align-content: center;
    background: transparent;
    padding: 0px 30px;
    z-index: 0
    //两侧的异形边框
    cyber_post_item_border()
    //顶栏
    .recent-post-item-headline
      cyber_post_item_line()
      .recent-post-time
        top: 20px;
        transition: var(--cyber-post-item-transition)
        cyber_post_item_time()
      .article-meta-sticky
        left: 20px
        bottom: 0;
        cyber_post_item_meta(-45deg,45deg,0 calc(100% - 25px) 0 0,1px 10px 0 30px,solid dashed solid groove)
        &:hover
          &~ .recent-post-time
            top: 40px;
            transition: var(--cyber-post-item-transition)
      .article-meta-comments
        right: 20px
        bottom: 0;
        cyber_post_item_meta(45deg,-45deg,0 0 0 calc(100% - 25px),1px 30px 0 10px,solid groove solid dashed)
        &:hover
          &~ .recent-post-time
            top: 40px;
            transition: var(--cyber-post-item-transition)
    //底栏
    .recent-post-item-bottomline
      cyber_post_item_line()
      .recent-post-time
        bottom:20px;
        transition: var(--cyber-post-item-transition)
        cyber_post_item_time()
      .article-meta-categories
        left: 20px
        top: 0;
        cyber_post_item_meta(45deg,-45deg,0 calc(100% - 30px) 0 0 ,0 10px 1px 30px,solid dashed solid groove)
        &:hover
          &~ .recent-post-time
            bottom: 40px;
            transition: var(--cyber-post-item-transition)
      .article-meta-tags
        right: 20px
        top: 0;
        cyber_post_item_meta(-45deg,45deg,0 0 0 calc(100% - 30px),0 30px 1px 10px,solid groove solid dashed)
        &:hover
          &~ .recent-post-time
            bottom: 40px;
            transition: var(--cyber-post-item-transition)
    //文章封面、标题、描述主体版块
    .recent-post-content
      display: flex;
      z-index: 0
      flex-direction: row;
      align-items: center;
      justify-content: center;
      background: transparent;
      position: relative;
      &:hover
        a.recent-post-description
          transform: rotateX(0deg)
          transition: var(--cyber-post-item-transition) 0.5s
      .recent-post-cover
        cyber_post_item_cover_title()
        img.article-cover
          object-fit: cover;
          height: 100%
          width: 100%;
      //文章标题
      .recent-post-info
        cyber_post_item_cover_title()
        .article-title-link
          margin: 20px 80px
          font-size: 24px;
          text-align: center;
          color: var(--cyber-post-item-font-color);
          display: -webkit-box;
          -webkit-box-orient: vertical;
          overflow: hidden;
          -webkit-line-clamp: 2
          cyber_post_item_link_hover()
      //装饰性背景图标
      svg.cyber-decoration
        position: absolute;
        z-index: 0;
        opacity: 0.3;
        color: var(--cyber-post-item-font-color); 
        width: 150px;
        height: 150px;
        top: calc(50% - 75px);
        left: calc(50% - 75px);
        cyber_post_item_link_hover()
      //文章描述内容
      a.recent-post-description
        z-index: 1
        position: relative;
        display: flex;
        align-items: center;
        justify-content: center;
        background: var(--cyber-post-item-screen);
        border-radius: 15px;
        box-shadow: 0 0 10px var(--cyber-post-item-box-shadow);
        transform: rotateX(90deg)
        transition: var(--cyber-post-item-transition)
        padding: 20px 20px;
        .article-content-text
          color: var(--cyber-post-item-font-color);
          text-shadow: 3px 3px 3px var(--cyber-post-item-text-shadow);
          overflow-y: scroll
          font-size: 16px;
          &::-webkit-scrollbar
            width 0px
//pc端样式适配
@media screen and (min-width:900px)
  // 卡片本体
  .recent-post-item
    &.cyber-post-card
      width: 100%;
      height: 320px;
      //文章封面、标题、描述主体版块
      .recent-post-content
        width: 100%;
        height: 240px;
        &.both,
        &.left
          &:hover
            .recent-post-cover
              cyber_post_item_left_content_hover()
            .recent-post-info
              cyber_post_item_right_content_hover()
        &.right
          &:hover
            .recent-post-cover
              cyber_post_item_right_content_hover()
            .recent-post-info
              cyber_post_item_left_content_hover()  
        .recent-post-cover
          width: 50%;
          height: 240px; 
        //文章标题
        .recent-post-info
          width: 50%;
          height: 240px; 
          .article-title-link
            margin: 20px 80px
            font-size: 24px;
        &.both,
        &.left
          .recent-post-cover
            cyber_post_item_left_content()
          .recent-post-info
            cyber_post_item_right_content()
        &.right
          .recent-post-cover
            cyber_post_item_right_content()
          .recent-post-info
            cyber_post_item_left_content()
        //文章描述内容
        a.recent-post-description
          height: 200px;
          margin: 20px 0
          width: 60%;
//平板宽度双栏样式适配
@media screen and (min-width:468px) and (max-width:900px)  
  #recent-posts
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    // 卡片本体
    .recent-post-item
      &.cyber-post-card
        width: 48%;
        height: 360px;
        margin: 0 1% 30px 1%
        //文章封面、标题、描述主体版块
        .recent-post-time
          .article-meta-label
            display: none
        .recent-post-content
          width: 100%;
          height: 280px;
          &:hover
            .recent-post-cover
              cyber_post_item_top_content_hover()
            .recent-post-info
              cyber_post_item_bottom_content_hover()
          .recent-post-cover
            width: 100%;
            height: 140px; 
            cyber_post_item_top_content()
          //文章标题
          .recent-post-info
            width: 100%;
            height: 140px; 
            cyber_post_item_bottom_content()
            .article-title-link
              margin: 10px 10px
              font-size: 18px;
          //文章描述内容
          a.recent-post-description
            height: 200px;
            margin: 40px 0
            width: 70%;       
//手机端样式适配
@media screen and (max-width:468px)
  // 卡片本体
  .recent-post-item
    &.cyber-post-card
      width: 100%;
      height: 360px;
      //文章封面、标题、描述主体版块
      .recent-post-time
        .article-meta-label
          display: none
      .recent-post-content
        width: 100%;
        height: 280px;
        &:hover
          .recent-post-cover
            cyber_post_item_top_content_hover()
          .recent-post-info
            cyber_post_item_bottom_content_hover()
        .recent-post-cover
          width: 100%;
          height: 140px; 
          cyber_post_item_top_content()
        //文章标题
        .recent-post-info
          width: 100%;
          height: 140px; 
          cyber_post_item_bottom_content()
          .article-title-link
            margin: 10px 10px
            font-size: 18px;
        //文章描述内容
        a.recent-post-description
          height: 200px;
          margin: 40px 0
          width: 70%;

0 人点赞