新博客的动画效果实现
最近重新写了 Ghost-theme 的主题。其中主要是取消了Icon-font,改为了SVG Sprite 。其次非常重要的板块首屏的Slide 和导航重新设计了。先看下具体的效果吧:
Slide 切换
切换动画
slide 的切换主要是利用了transform
和 animation
两个重要的属性。而切换的时间函数则需要用到 cubic-bezier
(关于贝塞尔曲线的效果可以参考这里)。然后利用少量的JS和手势库就可以完成了。
基本结构
<div id="slideshow" class="slideshow">
<!-- slide -->
<div class="slide">
<div class="bg-overlay" style="background-image:url(/content/images/2017/04/rocket-in-dark-1.jpg)"></div>
<blockquote>
<p>破立</p>
<a class="view-details noSwipe" href="/fan-fu/">
阅读详情 <svg style="margin-top:2px;" class="icon icon-fast-forward"><use xlink:href="#icon-fast-forward"></use></svg>
</a>
</blockquote>
</div>
<!-- end slide -->
<!-- repeat -->
</div>
其中我们可以看到容器 slideshow
里面 包含你需要存放的 slide
单元。每个 slide 由一张背景图片,和标题以及导航链接组成。下来我们添加一些样式,整个slide都是用的绝对定位,占满首屏:
.slideshow,
.slide,
.slide::after {
width: 100%;
height: 100%
}
.slideshow {
margin: 0;
padding: 0;
overflow: hidden;
position: relative;
transition: margin .6s;
-webkit-transition: margin .6s;
transition-timing-function: cubic-bezier(0.7,0,0.3,1);
-webkit-transition-timing-function: cubic-bezier(0.7,0,0.3,1);
background-color: #2c3e50
}
关于这使用的transition
后文的导航会涉及到。
接下来,我们添加slide里面的样式,
.slide {
position: absolute;
top: 0;
left: 0;
opacity: 0;
pointer-events: none;
background: #fff;
-webkit-transform-origin: 50% 120%;
transform-origin: 50% 120%
}
.slide::after {
position: absolute;
left: 0;
top: 0;
z-index: 1000;
background: #fff;
content: '';
opacity: 0;
-webkit-transition: opacity 4s;
transition: opacity 4s;
-webkit-transition-timing-function: cubic-bezier(0.7,0,0.3,1);
transition-timing-function: cubic-bezier(0.7,0,0.3,1)
}
.slideshow blockquote p {
overflow: hidden;
text-overflow: ellipsis;
padding: 0 .25rem
}
.slideshow blockquote {
z-index: 1001;
position: absolute;
bottom: 3rem;
left: 3rem;
right: 3rem;
padding: 0;
padding-bottom: 1rem;
border-left: none;
color: #fff;
text-align: left
}
.slideshow .bg-overlay {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
box-shadow: 0 -2rem 3rem -2rem rgba(0,0,0,0.45) inset,0 -3rem 3rem -2rem rgba(0,0,0,0.45) inset,0 -4rem 5rem -4rem rgba(0,0,0,0.35) inset,0 -10rem 3rem -3rem rgba(0,0,0,0.35) inset,0 -15rem 3rem -3rem rgba(0,0,0,0.35) inset,0 -20rem 5rem -3rem rgba(0,0,0,0.35) inset;
transition: opacity 0.6s;
-webkit-transition: opacity 0.6s;
-webkit-transition-timing-function: cubic-bezier(0.7,0,0.3,1);
transition-timing-function: cubic-bezier(0.7,0,0.3,1)
}
.open .slideshow .bg-overlay {
opacity: 0
}
.slideshow blockquote p {
margin: 0;
margin-bottom: 2.5rem;
padding: 0;
font-size: 4.8rem;
font-style: normal;
line-height: 1.2em
}
.slideshow blockquote .date {
font-size: 1.1rem;
color: #ccc
}
.slideshow blockquote .view-details {
display: inline-block;
padding: .5rem 1rem;
border: 1px solid rgba(255,255,255,0.55);
border-radius: .2rem;
color: #fff;
font-size: 1.4rem;
line-height: 1.2em;
box-shadow: 0 2px 4px -2px rgba(0,0,0,0.25)
}
其中 .slide 是使用的绝对定位,其中关键的是设置它的旋转中心,从上面的动图也可以看到是在中心旋转。而blockquote
则设置的用于显示一些基本的标题和链接挑战的样式设置。
接下来我们来实现具体的动画效果:
我们动画分为四种,即逆时针淡入与淡出,顺时针淡入与淡出。
首先我们先添加整体的动画函时间函数控制。这里主要是使用的 cubic-bezier(0.7,0,0.3,1)。
.slider--animInRight,
.slider--animInLeft,
.slider--animOutRight,
.slider--animOutLeft {
-webkit-animation-timing-function: cubic-bezier(0.7,0,0.3,1);
animation-timing-function: cubic-bezier(0.7,0,0.3,1);
-webkit-animation-duration: .9s;
animation-duration: .9s;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards
}
我们添加图片逆时针旋转进入的动画效果,slide上面的一张会向左旋转一定角度,然后显示在最上层。
.slider--animInLeft {
-webkit-animation-name: animInLeft;
animation-name: animInLeft
}
.slider--animInLeft {
z-index: 101;
opacity: 1
}
@-webkit-keyframes animInLeft {
from {
-webkit-transform: rotate3d(0,0,1,-20deg) translate3d(-100%,0,0);
opacity: 0
}
to {
-webkit-transform: rotate3d(0,0,1,0deg) translate3d(0,0,0);
transform: rotate3d(0,0,1,0deg) translate3d(0,0,0)
}
}
@keyframes animInLeft {
from {
-webkit-transform: rotate3d(0,0,1,-20deg) translate3d(-100%,0,0);
transform: rotate3d(0,0,1,-20deg) translate3d(-100%,0,0);
opacity: 0
}
to {
-webkit-transform: rotate3d(0,0,1,0deg) translate3d(0,0,0);
transform: rotate3d(0,0,1,0deg) translate3d(0,0,0)
}
}
同理,我们添加从右进入的动画效果:
.slider--animInRight {
z-index: 101;
opacity: 1
}
.slider--animInRight {
-webkit-animation-name: animInRight;
animation-name: animInRight
}
@-webkit-keyframes animInRight {
from {
-webkit-transform: rotate3d(0,0,1,20deg) translate3d(100%,0,0);
transform: rotate3d(0,0,1,20deg) translate3d(100%,0,0);
opacity: 0
}
to {
-webkit-transform: rotate3d(0,0,1,0deg) translate3d(0,0,0);
transform: rotate3d(0,0,1,0deg) translate3d(0,0,0)
}
}
@keyframes animInRight {
from {
-webkit-transform: rotate3d(0,0,1,20deg) translate3d(100%,0,0);
transform: rotate3d(0,0,1,20deg) translate3d(100%,0,0);
opacity: 0
}
to {
-webkit-transform: rotate3d(0,0,1,0deg) translate3d(0,0,0);
transform: rotate3d(0,0,1,0deg) translate3d(0,0,0)
}
}
其中我们还需要给进入的样式中设置:after
伪类的效果,让它的的透明度变为1。
.slider--animOutRight::after,
.slider--animOutLeft::after {
opacity: 1
}
同理,我们可以添加淡出的动画,分为左右两个方向。
.slider--animOutRight {
-webkit-animation-name: animOutRight;
animation-name: animOutRight
}
.slider--animOutLeft {
-webkit-animation-name: animOutLeft;
animation-name: animOutLeft
}
@-webkit-keyframes animOutLeft {
to {
-webkit-transform: rotate3d(0,0,1,-20deg) translate3d(-100%,0,0);
transform: rotate3d(0,0,1,-20deg) translate3d(-100%,0,0);
opacity: 0
}
}
@keyframes animOutLeft {
to {
-webkit-transform: rotate3d(0,0,1,-20deg) translate3d(-100%,0,0);
transform: rotate3d(0,0,1,-20deg) translate3d(-100%,0,0);
opacity: 0
}
}
@-webkit-keyframes animOutRight {
to {
-webkit-transform: rotate3d(0,0,1,20deg) translate3d(100%,0,0);
transform: rotate3d(0,0,1,20deg) translate3d(100%,0,0);
opacity: 0
}
}
@keyframes animOutRight {
to {
-webkit-transform: rotate3d(0,0,1,20deg) translate3d(100%,0,0);
transform: rotate3d(0,0,1,20deg) translate3d(100%,0,0);
opacity: 0
}
}
这样我们的样式基本就到位了,我们需要设置当前显示slider的样式。
.slider--current {
position: absolute;
z-index: 100;
opacity: 1;
pointer-events: auto
}
这样我们的基本效果就呈现了。
接着我们添加一些边角料的样式,比如用于控制的左右切换的按钮以及slide的缩略图。
.slideshow .ctrl {
z-index: 101;
position: absolute;
bottom: 3rem;
right: 3rem
}
.slideshow .ctrl a {
color: rgba(255,255,255,0.75);
margin: .5rem
}
.slideshow .ctrl a:hover,.slideshow .ctrl a.active {
color: #fff
}
.slideshow .thumb {
z-index: 101;
position: absolute;
bottom: 3rem;
left: 3.25rem
}
.slideshow .thumb a {
display: inline-block;
width: .5rem;
height: .5rem;
margin: .25rem;
border-radius: .5rem;
background-color: rgba(255,255,255,0.45)
}
.slideshow .thumb a.active {
background-color: rgba(255,255,255,0.85)
}
这些都是动态通过JS添加的,接下来我们添加JS来控制逻辑。首先我们需要引入 jQuery的库。
/* globals jQuery, document */
(function ($) {
"use strict";
var $document = $(document),
containers = [].slice.call($('.slide')),
containersCount = containers.length,
current = 0,
isAnimating = false,
pageTriggers = [];
var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
$document.ready(function () {
initSlider();
});
function initSlider() {
var thumbString = '';
containers.forEach(function (item, index) {
thumbString += '<a href="javascript:;" ' + (index === 0 ? 'class="active" ' : '') + '></a>';
});
if (containers.length > 1) {
var ctrlString = '';
if (!isMobile) {
ctrlString = '<div class="ctrl"><a href="javascript:;" class="js-ctrl-left" ><svg class="icon icon-rewind"><use xlink:href="#icon-rewind"></use></svg></a><a href="javascript:;" class="js-ctrl-right icon-angle-right" ><svg class="icon icon-fast-forward"><use xlink:href="#icon-fast-forward"></use></svg></a></div>';
}
$('#slideshow').append([ctrlString, '<div class="thumb">', thumbString, '</div>'].join(''));
bindEvent();
}
pageTriggers = [].slice.call($('.thumb a'));
$(containers[current]).addClass('slider--current');
}
function bindEvent() {
$('.js-ctrl-left').on('click', function () {
if (current > 0) {
navigate(pageTriggers[current - 1]);
}
});
$('.js-ctrl-right').on('click', function () {
if (current < containersCount - 1) {
navigate(pageTriggers[current + 1]);
}
});
function navigate(pageTrigger) {
var oldcurrent = current,
newcurrent = pageTriggers.indexOf(pageTrigger);
if (isAnimating || oldcurrent === newcurrent) return;
isAnimating = true;
var currentPageTrigger = pageTriggers[current],
nextContainer = containers[newcurrent],
currentContainer = containers[current],
dir = newcurrent > oldcurrent ? 'left' : 'right';
$(currentPageTrigger).removeClass('active');
$(pageTrigger).addClass('active');
// update current
current = newcurrent;
$(nextContainer).addClass(dir === 'left' ? 'slider--animInRight' : 'slider--animInLeft');
$(currentContainer).addClass(dir === 'left' ? 'slider--animOutLeft' : 'slider--animOutRight');
onEndAnimation(currentContainer, function () {
$(currentContainer).removeClass(dir === 'left' ? 'slider--animOutLeft' : 'slider--animOutRight');
$(nextContainer).removeClass(dir === 'left' ? 'slider--animInRight' : 'slider--animInLeft');
$(currentContainer).removeClass('slider--current');
$(nextContainer).addClass('slider--current');
isAnimating = false;
});
}
})(jQuery);
这样我们就可以就可以看到基本的效果了,其中 navigate
为最为核心的函数。主要是依据当前的slide然后去进行方向的选择,也就是添加不同的 class
。
我们看到其中有用到一些svg图标,所以我们还必须先在body里添加svg图标:
<!--svg -->
<svg style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<symbol id="icon-ribbon" viewBox="0 0 24 24">
<title>ribbon</title>
<path d="M7 1h10q1.242 0 2.121 0.879t0.879 2.121v19l-8-6-8 6v-19q0-1.242 0.879-2.121t2.121-0.879zM17 3h-10q-0.414 0-0.707 0.293t-0.293 0.707v15l6-4.5 6 4.5v-15q0-0.414-0.293-0.707t-0.707-0.293z"></path>
</symbol>
<symbol id="icon-image" viewBox="0 0 24 24">
<title>image</title>
<path d="M4 1h16q1.242 0 2.121 0.879t0.879 2.121v16q0 1.242-0.879 2.121t-2.121 0.879h-16q-1.242 0-2.121-0.879t-0.879-2.121v-16q0-1.242 0.879-2.121t2.121-0.879zM21 17.414l-5-5-8.586 8.586h12.586q0.414 0 0.707-0.293t0.293-0.707v-2.586zM20 3h-16q-0.414 0-0.707 0.293t-0.293 0.707v16q0 0.414 0.293 0.707t0.707 0.293h0.586l11.414-11.414 5 5v-10.586q0-0.414-0.293-0.707t-0.707-0.293zM8 5q1.242 0 2.121 0.879t0.879 2.121-0.879 2.121-2.121 0.879-2.121-0.879-0.879-2.121 0.879-2.121 2.121-0.879zM8 7q-0.414 0-0.707 0.293t-0.293 0.707 0.293 0.707 0.707 0.293 0.707-0.293 0.293-0.707-0.293-0.707-0.707-0.293z"></path>
</symbol>
<symbol id="icon-search" viewBox="0 0 24 24">
<title>search</title>
<path d="M10 1q1.828 0 3.496 0.715t2.871 1.918 1.918 2.871 0.715 3.496q0 1.57-0.512 3.008t-1.457 2.609l5.68 5.672q0.289 0.289 0.289 0.711 0 0.43-0.285 0.715t-0.715 0.285q-0.422 0-0.711-0.289l-5.672-5.68q-1.172 0.945-2.609 1.457t-3.008 0.512q-1.828 0-3.496-0.715t-2.871-1.918-1.918-2.871-0.715-3.496 0.715-3.496 1.918-2.871 2.871-1.918 3.496-0.715zM10 3q-1.422 0-2.719 0.555t-2.234 1.492-1.492 2.234-0.555 2.719 0.555 2.719 1.492 2.234 2.234 1.492 2.719 0.555 2.719-0.555 2.234-1.492 1.492-2.234 0.555-2.719-0.555-2.719-1.492-2.234-2.234-1.492-2.719-0.555z"></path>
</symbol>
<symbol id="icon-rewind" viewBox="0 0 24 24">
<title>rewind</title>
<path d="M18 4q0.414 0 0.707 0.293t0.293 0.707-0.297 0.711l-6.289 6.289 6.289 6.289q0.297 0.297 0.297 0.711t-0.293 0.707-0.707 0.293q-0.422 0-0.711-0.289l-7-7q-0.289-0.289-0.289-0.711t0.289-0.711l7-7q0.289-0.289 0.711-0.289zM12 4q0.414 0 0.707 0.293t0.293 0.707-0.297 0.711l-6.289 6.289 6.289 6.289q0.297 0.297 0.297 0.711t-0.293 0.707-0.707 0.293q-0.422 0-0.711-0.289l-7-7q-0.289-0.289-0.289-0.711t0.289-0.711l7-7q0.289-0.289 0.711-0.289z"></path>
</symbol>
<symbol id="icon-fast-forward" viewBox="0 0 24 24">
<title>fast-forward</title>
<path d="M11 4q0.414 0 0.703 0.289l7 7q0.297 0.297 0.297 0.711t-0.297 0.711l-7 7q-0.289 0.289-0.703 0.289t-0.707-0.293-0.293-0.707q0-0.422 0.289-0.711l6.289-6.289-6.289-6.289q-0.289-0.289-0.289-0.711 0-0.43 0.285-0.715t0.715-0.285zM5 4q0.414 0 0.703 0.289l7 7q0.297 0.297 0.297 0.711t-0.297 0.711l-7 7q-0.289 0.289-0.703 0.289t-0.707-0.293-0.293-0.707q0-0.422 0.289-0.711l6.289-6.289-6.289-6.289q-0.289-0.289-0.289-0.711 0-0.43 0.285-0.715t0.715-0.285z"></path>
</symbol>
<symbol id="icon-speech-bubble" viewBox="0 0 24 24">
<title>speech-bubble</title>
<path d="M4 1h16q1.242 0 2.121 0.879t0.879 2.121v11q0 1.242-0.879 2.121t-2.121 0.879h-8l-7 5v-5h-1q-1.242 0-2.121-0.879t-0.879-2.121v-11q0-1.242 0.879-2.121t2.121-0.879zM20 3h-16q-0.414 0-0.707 0.293t-0.293 0.707v11q0 0.414 0.293 0.707t0.707 0.293h3v3.117l4.359-3.117h8.641q0.414 0 0.707-0.293t0.293-0.707v-11q0-0.414-0.293-0.707t-0.707-0.293z"></path>
</symbol>
<symbol id="icon-pie-graph" viewBox="0 0 24 24">
<title>pie-graph</title>
<path d="M12 1q2.242 0 4.277 0.871t3.508 2.344 2.344 3.508 0.871 4.277-0.871 4.277-2.344 3.508-3.508 2.344-4.277 0.871-4.277-0.871-3.508-2.344-2.344-3.508-0.871-4.277 0.871-4.277 2.344-3.508 3.508-2.344 4.277-0.871zM11 13v-9.945q-1.664 0.188-3.145 0.965t-2.547 1.957-1.688 2.75-0.621 3.273q0 1.828 0.715 3.496t1.918 2.871 2.871 1.918 3.496 0.715q1.703 0 3.273-0.621t2.75-1.688 1.957-2.547 0.965-3.145h-9.945zM13 3.055v7.945h7.945q-0.172-1.547-0.852-2.934t-1.727-2.434-2.434-1.727-2.934-0.852z"></path>
</symbol>
<symbol id="icon-star" viewBox="0 0 24 24">
<title>star</title>
<path d="M9.297 9l2.703-8.32 2.703 8.32h8.75l-7.078 4.914 2.703 8.172-7.078-5.18-7.078 5.141 2.703-8.133-7.078-4.914h8.75zM13.25 11l-1.25-3.977-1.25 3.977h-3.883l3.125 2.070-1.227 3.695 3.242-2.344 3.227 2.367-1.227-3.695 3.117-2.094h-3.875z"></path>
</symbol>
</defs>
</svg>
<!--svg end-->
添加图标样式
.icon {
display: inline-block;
width: 1em;
height: 1em;
stroke-width: 0;
stroke: currentColor;
fill: currentColor;
vertical-align: middle
}
导航的动画
从动画中,我们还看到了向下滑的时候,会看到导航的链接出现,也就是点击右上角的 图标按钮 后出现的效果。接下来我们再添加这样的效果。
<div class="nav">
<div class="container">
<div class="nav-list">
<div class="avatar">
<img src="http://img1.vued.vanthink.cn/vuedf926d9e80d3eb33c504228105f872e3c.png" />
</div>
<div class="quote">
Jack Pu's Blog (蒲小花的博客-ポーのブログ)
</div>
<a href="http://www.jackpu.com/">Home</a>
<a href="https://www.behance.net/codeui">Design</a>
<a href="http://www.jackpu.com/tag/web/">Web</a>
<a href="http://me.jackpu.com/">About Me</a>
</div>
<a href="javascript:;" class="menu-icon open">
<svg width="100%" height="100%" viewBox="0 0 60 60" preserveAspectRatio="none">
<g id="icon-grid">
<rect x="32.5" y="5.5" width="22" height="22"></rect>
<rect x="4.5" y="5.5" width="22" height="22"></rect>
<rect x="32.5" y="33.5" width="22" height="22"></rect>
<rect x="4.5" y="33.5" width="22" height="22"></rect>
</g>
<g id="icon-cross">
<line x1="4.5" y1="55.5" x2="54.953" y2="5.046"></line>
<line x1="54.953" y1="55.5" x2="4.5" y2="5.047"></line>
</g>
</svg>
</a>
</div>
</div>
基本的结构,就是简单的导航链接和控制的svg按钮。
接下来我们添加它的基本样式,它默认是只会出现一个 如下图的按钮菜单。
.nav {
overflow: hidden;
z-index: 1000;
position: absolute;
top: 0;
left: 0;
right: 0;
height: 7rem;
margin-bottom: 0;
text-align: center;
font-size: 1.5rem;
opacity: 1;
transition: height .6s;
transition-timing-function: cubic-bezier(0.7,0,0.3,1)
}
.nav .container {
position: relative;
width: 1170px;
height: 100%;
line-height: 7rem;
margin: 0 auto
}
.open .nav {
height: 100%;
background-color: #fff
}
.open .nav .nav-list {
opacity: 1;
transform: translateY(0)
}
.nav-list {
opacity: 0;
padding-top: 5rem;
margin: 0 4rem;
text-align: center;
font-size: 2rem;
line-height: 4rem;
transition: all .65s;
transform: translateY(-520px);
transition-timing-function: cubic-bezier(0.7,0,0.3,1)
}
.nav-list .avatar {
display: inline-block;
width: 12rem;
height: 12rem;
border-radius: 6rem;
border: 0.3rem solid #111;
text-align: center;
overflow: hidden
}
.nav-list .avatar img {
width: 100%;
height: 100%
}
.nav-list .quote {
font-size: 1.8rem;
color: #777
}
.nav-list a {
overflow: hidden;
display: block;
width: 20rem;
height: 4rem;
margin: 0 auto;
border-radius: 2rem;
white-space: nowrap;
text-overflow: ellipsis;
transition: all .25s ease;
text-decoration: underline;
color: #333;
transition: all .2s ease
}
.nav-list a:active {
background: linear-gradient(to left,#ee8326,#ef1d27);
color: #fff;
text-decoration: none
}
.nav-list a:hover {
color: #000
}
.menu-icon {
position: absolute;
right: 0;
bottom: 0;
width: 2.4rem
}
.menu-icon #icon-grid,.menu-icon #icon-cross {
opacity: 0;
stroke: #f1f1f1;
stroke-width: 2px;
fill: none;
transition: all 0.3s ease-in
}
.menu-icon #icon-cross {
opacity: 1
}
.menu-icon.open #icon-cross {
opacity: 0
}
.menu-icon.open #icon-grid {
opacity: 1
}
.open .nav .menu-icon #icon-cross {
stroke: #333
}
其中,我们可以看到会有 .open 这个 class的存在,实际上它是作用于 body 上的。而添加 open
后,按钮的样式会有小方块变成关闭的按钮,这是用过 svg 的样式控制来实现的。而 nav 这个导航的样式也会有所变化 高度会变成 100%。同时,下面的 slideshow 也会配合动画效果,有下面的样式变化:
.open .slideshow {
margin-top: 480px
}
.open .slideshow .bg-overlay {
opacity: 0
}
其中距离顶部高度会变化,而且里面的图片也会变得透明,这样会有淡出的效果。
当然我们需要在 JS 中添加这些控制:
$('.menu-icon').on('click', function (e) {
$('body').toggleClass('open');
$(this).toggleClass('open');
});
添加手势
对于手势的支持,我们需要引入 jquery.swipe,这个时候我们添加对于手势的处理,
$("#slideshow").swipe({
//Generic swipe handler for all directions
swipe: function (event, direction, distance, duration, fingerCount, fingerData) {
if (direction == 'left') {
if (current < containersCount - 1) {
navigate(pageTriggers[current + 1]);
}
} else if (direction == 'right') {
if (current > 0) {
navigate(pageTriggers[current - 1]);
}
} else if (direction == 'down') {
var sT = $('html').scrollTop();
if(sT == 0) {
$('body').toggleClass('open');
$('.menu-icon').toggleClass('open');
} else {
$('html').animate({'scrollTop': 0},500);
}
} else if(direction == 'up'){
return false;
}
},
threshold: 0,
allowPageScroll: 'vertical',
});
}
这样我们就实现了这次新的 slide 的效果, 你可以点击回到主页查看效果。主题项目 github 地址: https://github.com/JackPu/ghost-theme