Hexo博客 | 如何为博客添加顶部轮播图和文章推荐卡片

2022-09-02 09:00:53 浏览数 (1)

最近看了zhheo大佬的博客首页,发现大佬的布局还是那么的好看,于是果断COPY,再加上我一直想要在我的博客首页加一个大画幅的轮播图插件,于是又参考了Hassan的文章轮播图…经过一番折腾,效果如下:

1. 创建首页顶部模块

1.1 创建hometop.pug

themes/butterfly/layout/includes路径下创建hometop.pug文件:

代码语言:javascript复制
if is_home()
  #home_top
    include bbTimeList.pug
    .home_top_group
      #homeTopGroup.homeTopGroup
        #banner_group
          #banners
            include sticky.pug //轮播图
          .category_group
            .category_item
              a.category_button(href=<左下角标签1路径>,style="background:linear-gradient(to right,#364f6b,#3fc1c9)")
                span.category_button_text <标签1名称>
                i.fas.fa-laptop-code
            .category_item
              a.category_button(href=<左下角标签2路径>,style="background:linear-gradient(to right,#6639a6,#3490de)")
                span.category_button_text <标签2名称>
                i.fas.fa-lightbulb
            .category_item
              a.category_button(href=<左下角标签3路径>,style="background:linear-gradient(to right,#f65,#ffbf37)")
                span.category_button_text <标签3名称>
                i.fas.fa-book
        .top_post_group // 右侧文章推荐卡片
          if site.data.slider
            each i in site.data.slider
              .top_post_item
                .post_cover
                  a(href=url_for(i.link) title=i.title)
                    img.post_bg.entered.loaded(src=url_for(i.cover))
                    .post_cover_info
                      p.post_cover_text= i.description

                .post_info(onclick=`"window.open(` url_for(i.link) `,"_self")"`)
                  a.article-title(href=url_for(i.link) title=i.title)= i.title

其中第一行的is_home()Hexo自带的辅助函数,用于判断是否为首页,但是其在justlovesmile.top/以及justlovesmile.top/page/2/等页面都返回True,因此如果你只想在首页的第一页显示该模块,可以使用is_current('/')

1.2 添加css样式

在自己的css文件中添加:

代码语言:javascript复制
:root{
    --mj-white: #fff;
    --mj-card-bg: #fff;
    --mj-theme: #425AEF;
    --mj-main: #425AEF;
    --mj-secondbg: #ededed;
    --mj-card-border: #e3e8f7;
    --style-border: 1px solid var(--mj-card-border);
    --style-hover-border: 1px solid var(--mj-theme);
}
/* home top */
#home_top {
    max-width: 1500px;
    width: 100%;
    margin-top: .5rem;
    padding: 0 15px;
    margin: 0 auto;
}
.home_top_group {
    border-radius: 12px;
    overflow: auto;
    width: 100%;
    margin-bottom: 0;
}
.homeTopGroup {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    width: 100%;
    margin-top: 1rem;
    overflow: auto;
    overflow-x: score;
    border-radius: 12px;
}
.homeTopGroup::-webkit-scrollbar {
    display: none;
}
.homeTopGroup #banner_group {display: flex;}
div#banners {display: none;}
@media screen and (min-width: 1300px){
  .homeTopGroup #banner_group {
    width: calc(100% - 600px - 1.5rem);
    display: flex;
    flex-direction: column;
    justify-content: space-between;
  }
  div#banners {
    display: flex;
    width: 100%;
    height: 100%;
    background: var(--mj-main);
    margin-bottom: .5rem;
    margin-right: .5rem;
    border: var(--style-border);
    border-radius: 12px;
    overflow: hidden;
    position: relative;
  }
  div#banners:hover{
    border: var(--style-hover-border);
  }
  .homeTopGroup .category_group {
    flex-direction: row !important;
  }
  .homeTopGroup .category_item {
    width: calc(100% / 3 - .33rem);
    height: 100% !important;
    margin-right: .5rem;
  }
  .homeTopGroup .category_item:nth-child(3) {
    margin-right: 0;
    display: flex !important;
  }
  #banner-page {
    width: 100%;
    height: 100%;
  }
  .top_post_group {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: flex-end;
    height: calc(328px   .5rem);
    align-content: space-between;
    width: calc(600px   1.5rem);
  }
}

.homeTopGroup .category_group{
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    min-width: 200px;
}
.homeTopGroup .category_item {
    overflow: hidden;
    transform: scale(1);
    transition: .3s;
    height: 48%;
    border-radius: 12px;
}
.homeTopGroup .category_item:nth-child(3) {
    display: none;
}
.homeTopGroup .category_item a.category_button {
    height: 100%;
    width: 100%;
    background: var(--mj-card-bg);
    border-radius: 12px;
    display: inline-block;
    text-align: left;
    line-height: 4em;
    font-weight: 700;
    font-size: .9rem;
    color: var(--mj-white);
    transition: all .4s cubic-bezier(.39,.575,.565,1);
    transform: scale(1);
    overflow: hidden;
    font-family: PingFang SC,Hiragino Sans GB,Microsoft YaHei;
}
.category_button_text {
    padding-left: 25px;
}
a.category_button i {
    font-size: 3rem;
    opacity: .3;
    position: absolute;
    right: 15px;
    top: 10%;
    transition: .3s;
    transform: rotate(-10deg);
    /*width: 100px;
    text-align: center;*/
}
a.category_button:hover i {
    opacity: .8;
    transition: .8s;
    transition-delay: .15s;
    transform: scale(1.1)
}
a.category_button:hover:after{
    width: 3rem;
    transition: .8s;
}
a.category_button:after {
    top: 40px;
    width: 1rem;
    left: 25px;
    height: 2px;
    background: var(--mj-white);
    content: "";
    border-radius: 1px;
    position: absolute;
    transition: .8s;
}
@media screen and (max-width: 768px){
  #home_top{
    padding: 0 5px;
  }
  .homeTopGroup .category_group {
    min-width: 130px!important;
  }
  .top_post_group .top_post_item{
    border-radius: 0;
  }
}
.top_post_group{
    display: flex;
    position: relative;
}
.top_post_group .top_post_item {
    display: flex;
    width: 200px;
    min-width: 200px;
    height: 164px;
    max-height: 164px;
    flex-direction: column;
    align-items: flex-start;
    margin-left: .5rem;
    background: var(--mj-card-bg);
    border-radius: 12px;
    overflow: hidden;
    border: var(--style-border);
}
.top_post_group .top_post_item:hover {border: var(--style-hover-border);}
.top_post_group .top_post_item .post_cover {
    width: 100%;
    height: 110px;
    position: relative;
}
.top_post_group .top_post_item .post_cover img {
    object-fit: cover;
    width: 100%;
    height: 110px;
    background: var(--mj-secondbg);
}
.top_post_group .top_post_item .post_cover .post_cover_info {
    position: absolute;
    top: 0;
    width: 101%;
    height: 100%;
    opacity: 0;
    background-color: rgba(0,0,0,0.7) !important;
    transition: all 0.3s ease;
    display: flex;
} 
.top_post_group .top_post_item:hover .post_cover .post_cover_info{
    opacity: 1;
}
.top_post_group .top_post_item .post_cover .post_cover_info .post_cover_text{
    color: #fff;
    padding: 12px 14px;
    font-size: 15px;
    font-weight: 400;
    margin: 20px 0;
    -webkit-line-clamp: 2;
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
}
.top_post_group .top_post_item:hover .post_info,
.top_post_group .top_post_item:focus .post_info{
    /*background: var(--mj-theme);*/
    box-shadow: inset 0 -60px 0 0 var(--mj-theme);
}
.top_post_group .top_post_item .post_info a{
    color: var(--mj-fontcolor) !important;
    transition: 0;
}
.top_post_group .top_post_item:hover .post_info a{
    color: var(--mj-white) !important;
}
.top_post_group .top_post_item .post_info {
    padding: .2rem .5rem .3rem .5rem!important;
    transition: .3s;
    width: 100%;
    height: 100%;
}
.top_post_group .top_post_item .post_info .article-title {
    -webkit-line-clamp: 2;
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    line-height: 1.4;
    justify-content: center;
    align-items: flex-end;
    align-content: center;
    font-weight: 600;
    font-size: .8rem!important;
    padding: 0!important;
}

2. 创建顶部轮播图

2.1 创建sticky.pug

themes/butterfly/layout/includes路径下创建sticky.pug文件:

代码语言:javascript复制
link(rel='stylesheet' href='https://unpkg.com/swiper/swiper-bundle.min.css')
#sticky
  #stickyList.swiper-container
    #stickyWrapper.swiper-wrapper
      .swiper-slide(onclick=`window.open('/random/','_self')`)
        .grid-img
          iframe#banner-page(src="<这里放iframe地址>" frameborder="0" loading="eager") // 可以放iframe
        .grid-title
          span 随便逛逛
          i.fas.fa-arrow-right
      .swiper-slide(onclick=`window.open('/video/','_self')`)
        .grid-img
          img.cover.entered.loaded(alt='VLOG' src='https://npm.elemecdn.com/justlovesmile-photo/myvlog.gif') // 可以放GIF
        .grid-title
          span 看看VLOG
          i.fas.fa-arrow-right
      .swiper-slide(onclick=`window.open('/music/','_self')`)
        .grid-img
          img.cover.entered.loaded(alt='歌单' src='https://npm.elemecdn.com/justlovesmile-img/gitar.jpg') // 可以放图片
        .grid-title
          span 听听音乐
          i.fas.fa-arrow-right
    //- 分页器
    .swiper-pagination

.js-pjax
  script(src='https://unpkg.com/swiper/swiper-bundle.min.js')
  script(src='/js/sticky.js')
link(rel='stylesheet' href='/css/sticky.css')

2.2 创建sticky.js

themes/butterfly/source/js路径下创建sticky.js文件:

代码语言:javascript复制
var mySwiper = new Swiper('#stickyList', {
      direction: 'horizontal',
      speed: 600,
      loop: true,
      effect : 'fade',
      loopPreventsSlide: false,
      autoplay: {
        delay: 20000,
      },
      mousewheel: false,
      pagination: {
          el: ".swiper-pagination",
          dynamicBullets: true,
      },
    })

2.3 创建sticky.css

themes/butterfly/source/css路径下创建sticky.css文件:

代码语言:javascript复制
:root{
    --mj-white: #fff;
    --mj-card-bg: #fff;
    --mj-theme: #425AEF;
}
#sticky,
#stickyList,
#stickyWrapper{
  width: 100%;
  height: 100%;
}
.swiper-container#stickyList {
  overflow: hidden;
}
#stickyList .swiper-slide {
  background: var(--mj-card-bg);
  position: relative;
  border-radius: 12px;
  transition: 0.3s;
  width: 100%;
  height: 100%;
}
#stickyList .swiper-slide .grid-img {
  overflow: hidden;
  height: 16.2rem;
}
#stickyList .swiper-slide .grid-img img {
  transition: 0.3s;
  object-fit: cover;
  display: block;
  width: 100%;
  height: 100%;
}
#stickyList .swiper-slide:hover .grid-title{
  opacity: .8;
  cursor: pointer !important;
}
#stickyList .swiper-slide:hover .grid-img{
  filter: blur(5px);
}
#stickyList .swiper-slide:hover .grid-title span,
#stickyList .swiper-slide:hover .grid-title i{
  transform: translateX(0px);
  transition: .5s;
}
#stickyList .swiper-slide .grid-title span,
#stickyList .swiper-slide .grid-title i{
  transform: translateX(-100px);
  transition: .5s;
}
#stickyList .swiper-slide .grid-title {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  overflow: hidden;
  background: var(--mj-theme);
  color: var(--mj-white);
  padding-left: 1.5rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  opacity: 0;
  transition: .5s;
}
#stickyList .swiper-slide .grid-title span {
  font-size: 5rem;
  font-weight: 700;
  line-height: 5rem;
}
#stickyList .swiper-slide .grid-title i {
    font-size: 4rem;
    opacity: .6;
}
@media screen and (max-width: 768px) {
  #sticky {
    display: none;
  }
}

3. 创建文章推荐卡片

3.1 创建slider.yml

hexosource_data路径下创建slider.yml文件,最好准备6个推荐文章,例如:

代码语言:javascript复制
#- cover: 封面图片链接
#  timeline: '2020-10-01' # 日期,需要用''包裹
#  link: 置顶文章链接,站内文章建议填相对链接
#  title: 置顶文章标题
#  description: 置顶文章描述
- cover: https://npm.elemecdn.com/justlovesmile-img/20200715201402.png
  timeline: '2020-07-15'
  link: /posts/c8972b63.html
  title: 必看 | Hexo博客搭建超级指南
  description: Hexo博客搭建全过程,环境部署,博客魔改等等...
- cover: https://npm.elemecdn.com/justlovesmile-img/090412-1557363852af44.jpg
  timeline: '2020-04-09'
  link: /posts/56163.html
  title: Hexo博客 | 博客中能用到的代码(一)
  description: 这篇文章介绍了如何使用font awesome图标字体库,使用动态图标,添加网页运行时间,全站变黑白,鼠标点击特效,网页标题的动态效果,网页樱花特效,鼠标触动音乐特效
- cover: https://npm.elemecdn.com/justlovesmile-img/095658-1562983018e455.jpg
  timeline: '2020-04-09'
  link: /posts/15391.html
  title: Hexo博客 | 博客中能用到的代码(二)
  description: 这篇文章介绍了如何添加旋转小人和每日诗句
- cover: https://npm.elemecdn.com/justlovesmile-img/20220331192754.png
  timeline: '2022-03-31'
  link: /posts/a806bebe.html
  title: 推荐 | 计算机专业,大学课程「笔记归档」
  description: 本文是博主本科期间的专业课程学习笔记的整理和归档,适合计算机专业的同学阅读。
- cover: https://npm.elemecdn.com/justlovesmile-img/20220318183107.png
  timeline: '2022-03-18'
  link: /posts/589ec011.html
  title: 深度学习 | Detectron2使用指南
  description: Detectron2是Facebook AI Research的检测和分割框架,其主要基于PyTorch实现,但具有更模块化设计,因此它是灵活且便于扩展的。
- cover: https://npm.elemecdn.com/justlovesmile-img/202109111517311.jpg
  timeline: '2021-09-11'
  link: /posts/865c56ba.html
  title: 目标检测 | 常用数据集标注格式及生成脚本
  description: 目标检测是计算机视觉任务中的一个重要研究方向,是计算机视觉的根本性问题之一,是其他诸多计算机视觉任务的基础以及前提。本文主要介绍了目标检测数据集的几种标注格式和转换代码。

3.2 css样式

1.2.top_post_group等样式类,不再赘述…

4. 补充:zhheo大佬首页人来人往特效

4.1 创建people页面

hexosource路径下创建people文件夹,其中创建index.html:

代码语言:javascript复制
---
layout: false
---

<!doctype html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>MJ's People Page</title>
	<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0, minimal-ui" /><!--禁止缩放-->
	<link rel="stylesheet" href="/people/style.css">
</head>
<body>
	<canvas id="canvas" width="808" height="244"></canvas>
	<script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/gsap/3.9.1/gsap.min.js"></script>
	<script src="/people/script.js"></script></body>
</html>

4.2 创建css样式

hexosourcepeople路径下,创建style.css:

代码语言:javascript复制
body,
html{
	height:100%;
	background-color:#fff;
}
body{
	margin:0;
}
#canvas{
	width:100%;
	height:100%;
}
body::-webkit-scrollbar{
	display:none;
}

4.3 创建js文件

hexosourcepeople路径下,创建script.js:

代码语言:javascript复制
"use strict";function _toConsumableArray(e){return _arrayWithoutHoles(e)||_iterableToArray(e)||_unsupportedIterableToArray(e)||_nonIterableSpread()}function _nonIterableSpread(){throw new TypeError("Invalid attempt to spread non-iterable instance.nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _unsupportedIterableToArray(e,r){if(e){if("string"==typeof e)return _arrayLikeToArray(e,r);var t=Object.prototype.toString.call(e).slice(8,-1);return"Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t?Array.from(e):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?_arrayLikeToArray(e,r):void 0}}function _iterableToArray(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function _arrayWithoutHoles(e){if(Array.isArray(e))return _arrayLikeToArray(e)}function _arrayLikeToArray(e,r){(null==r||r>e.length)&&(r=e.length);for(var t=0,a=new Array(r);t<r;t  )a[t]=e[t];return a}function _classCallCheck(e,r){if(!(e instanceof r))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,r){for(var t=0;t<r.length;t  ){var a=r[t];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,a.key,a)}}function _createClass(e,r,t){return r&&_defineProperties(e.prototype,r),t&&_defineProperties(e,t),e}var config={src:"https://npm.elemecdn.com/guli-heo/others/open-peeps-sheet.png",rows:15,cols:7},randomRange=function(e,r){return e Math.random()*(r-e)},randomIndex=function(e){return 0|randomRange(0,e.length)},removeFromArray=function(e,r){return e.splice(r,1)[0]},removeItemFromArray=function(e,r){return removeFromArray(e,e.indexOf(r))},removeRandomFromArray=function(e){return removeFromArray(e,randomIndex(e))},getRandomFromArray=function(e){return e[0|randomIndex(e)]},resetPeep=function(e){var r,t,a=e.stage,n=e.peep,o=.5<Math.random()?1:-1,i=100-250*gsap.parseEase("power2.in")(Math.random()),s=a.height-n.height i;return 1==o?(r=-n.width,t=a.width,n.scaleX=1):(r=a.width n.width,t=0,n.scaleX=-1),n.x=r,n.y=s,{startX:r,startY:n.anchorY=s,endX:t}},normalWalk=function(e){var r=e.peep,t=e.props,a=(t.startX,t.startY),n=t.endX,o=gsap.timeline();return o.timeScale(randomRange(.5,1.5)),o.to(r,{duration:10,x:n,ease:"none"},0),o.to(r,{duration:.25,repeat:40,yoyo:!0,y:a-10},0),o},walks=[normalWalk],Peep=function(){function a(e){var r=e.image,t=e.rect;_classCallCheck(this,a),this.image=r,this.setRect(t),this.x=0,this.y=0,this.anchorY=0,this.scaleX=1,this.walk=null}return _createClass(a,[{key:"setRect",value:function(e){this.rect=e,this.width=e[2],this.height=e[3],this.drawArgs=[this.image].concat(_toConsumableArray(e),[0,0,this.width,this.height])}},{key:"render",value:function(e){e.save(),e.translate(this.x,this.y),e.scale(this.scaleX,1),e.drawImage.apply(e,_toConsumableArray(this.drawArgs)),e.restore()}}]),a}(),img=document.createElement("img");img.onload=init,img.src=config.src;var canvas=document.querySelector("#canvas"),ctx=canvas.getContext("2d"),stage={width:0,height:0},allPeeps=[],availablePeeps=[],crowd=[];function init(){createPeeps(),resize(),gsap.ticker.add(render),window.addEventListener("resize",resize)}function createPeeps(){for(var e=config.rows,r=config.cols,t=e*r,a=img.naturalWidth/e,n=img.naturalHeight/r,o=0;o<t;o  )allPeeps.push(new Peep({image:img,rect:[o%e*a,(o/e|0)*n,a,n]}))}function resize(){stage.width=canvas.clientWidth,stage.height=canvas.clientHeight,canvas.width=stage.width*devicePixelRatio,canvas.height=stage.height*devicePixelRatio,crowd.forEach(function(e){e.walk.kill()}),crowd.length=0,availablePeeps.length=0,availablePeeps.push.apply(availablePeeps,allPeeps),initCrowd()}function initCrowd(){for(;availablePeeps.length;)addPeepToCrowd().walk.progress(Math.random())}function addPeepToCrowd(){var e=removeRandomFromArray(availablePeeps),r=getRandomFromArray(walks)({peep:e,props:resetPeep({peep:e,stage:stage})}).eventCallback("onComplete",function(){removePeepFromCrowd(e),addPeepToCrowd()});return e.walk=r,crowd.push(e),crowd.sort(function(e,r){return e.anchorY-r.anchorY}),e}function removePeepFromCrowd(e){removeItemFromArray(crowd,e),availablePeeps.push(e)}function render(){canvas.width=canvas.width,ctx.save(),ctx.scale(devicePixelRatio,devicePixelRatio),crowd.forEach(function(e){e.render(ctx)}),ctx.restore()}

5. 参考文章

张洪Heo - 分享设计与科技生活 Butterfly主题美化魔改集锦 | Hassan’s Blog

0 人点赞