新博客改造的一些有趣的技术要点

最近随着 Ghost 升级,博客主题也做了一些动效的调整,这里面有一些比较有意思的细节,可以和大家分享下。

Ghost-Theme

落地页动画衔接

从首页列表点击进去,实际上是比较简单的 transition 过渡,主要是利用透明度变化和背景图片的放大缩小来完成的。

.cover,
.overlay{
    content: '';
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 100%;
    background-color: #000;
    background-position: center center;
    opacity: .2;
    background-size: cover;
}
.cover{
   opacity: 0;
   transition: opacity 1.5s, transform 2s;
   transition-timing-function: cubic-bezier(0.5, 0, 0.2, 1);
   background-color: transparent;
   transform: scale(1.2, 1.2);
}


&.loaded {
    .cover{
        opacity: 1;
        transform: scale(1, 1);
    }
}

而列表页的反之,是 hover 后进行放大

&:hover{
    .cover{
        opacity: .75;
        transform: scale(1.2, 1.2);
    }
}

视察滚动 (Parallax Scrolling)

Parallax Scrolling是最近几年一直都非常火的的交互效果,而这次博客改版在三处用到了 parallax scrolling。分别是首页 header ,详情页 header, 个人联系方式的 footer 处。

头部的动效是利用了 background-attachment 的属性,它可以用来表示背景图像是否固定或者随着页面的其余部分滚动。项目中我们设置了 fixed ,这样就会出现内容滚动但是背景图像依旧保持位置。

.slideshow .bg-overlay {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-position: center center;
    background-repeat: no-repeat;
    background-size: cover;
    background-attachment: fixed; // set this value
    box-shadow: 0 -2rem 3rem -2rem rgba(0, 0, 0, .45) inset, 0 -3rem 3rem -2rem rgba(0, 0, 0, .45) inset, 0 -4rem 5rem -4rem rgba(0, 0, 0, .35) inset, 0 -10rem 3rem -3rem rgba(0, 0, 0, .35) inset, 0 -15rem 3rem -3rem rgba(0, 0, 0, .35) inset, 0 -20rem 5rem -3rem rgba(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);
}

SNS Footer 的特效

这里是利用 JS 的 scrollTop 值太进行计算的。我们通过获取滚动条距离顶部的高度,然后再通过 设置 background-position 或者 transllateY 来进行动态更新。

$(document.body).on('scroll', function(e) {
    var top = e.target.scrollTop;
    var wH = window.innerHeight;
    if (top > 70 && top <= wH) {
        $('.overlay').css({
            opacity: 0.2 + 0.8 * (top / wH),
        });
        $('.js-post-meta').css({
            opacity: 1 - 0.8 * (top / wH),
            transform: 'translateY(' + top / 3 + 'px)',
        });
        $('.js-post-cover').css({
            backgroundPositionY: '-' + top / 4 + 'px',
        });
    } else if(top < 70) {
        $('.js-post-cover').css({
            backgroundPositionY: '0px',
        });
    }
    var ratio = 1;
    if (isMobile) {
        ratio = 3;
    }
    if (top > (contentHeight - 700)) {
	     // ... code
        $('.blur-circle.lg').css({
            // opacity: 1 - 0.8 * (top / wH),
             transform: 'translateY(' + (contentHeight - top - 700) / (2 * ratio) + 'px)',
         });
    }

});

SVG Filter

页面多出用到了 SVG ,除了目前所有的 ICON 用到了 svg-sprite ,这次还利用 gradient 和 filter 去实现球的模糊效果。

<svg width="120px" height="120px" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
    <defs>
        <linearGradient id="gradient4">
            <stop offset="5%" stop-color="#5573e3" />
            <stop offset="95%"  stop-color="#7022ed" />
        </linearGradient>
        <filter id="f4" x="0" y="0">
            <feGaussianBlur in="SourceGraphic2" stdDeviation="2" />
        </filter>
    </defs>
    <circle cx="50" fill="url(#gradient4)" filter="url(#f4)" cy="50" r="35"/>
</svg>

关于 feGaussianBlur 可以到官方 MDN 了解。

CSS LONG Shadow

Tag 页面放了一个 基于 less 实现的 长投影-long shadow

.longshadow(@color: #e3e3e3, @angle: 45, @size: 10, @flag: 1, @temp: "") when (@size > 0) {
  @angle360: @angle * (pi() / 180);
  @x: round(@flag * cos(@angle360));
  @y: round(@flag * sin(@angle360));
  @shadow: ~"@{x}px @{y}px 0px @{color}";
  @close: ~"@{shadow}, @{temp}";
  @alltogether: ~"@{close} 0px 0px 0px @{color}";

  .loop(@string, @index) when (@index < 1) {
      text-shadow: @string;
  }

  .loop(@alltogether, @size - 1);
  .longshadow(@color, @angle, @size - 1,@flag + 1, @close);
}

CodePen 演示地址

扩展阅读