SVG 应用:使用 SVG path (路径) 实现酷炫的页面过渡效果

3,863 阅读4分钟
原文链接: svgtrick.com

SVG的path(路径)是一个非常强大的属性!使用它可以实现很多的有趣的动画效果,比如现在很流行的描边绘制动画效果等等。

今天这篇文章就是使用SVG path(路径)来实现一个酷炫的页面过渡动画效果。为了提高开发效率,这里使用PugSass来这两个HTML和CSS预编译语言来编写HTML和CSS。

要实现的效果如下图所示,灵感主要是来源于Clément Brichon在Dribble上的一个效果。

这个效果实现的一个思路是,使用SVG path(路径)来实现一个黑色的图层盖在背景图片上,然后通过改变path(路径)的属性来实现途中所示的动画效果。

要注意一点的是,SVG到现在为止不是所有的浏览器都支持,特别是桌面设备上。不过在chrome等现代浏览器上是没问题的。

SVG path动画

这个动画主要是使用SVG path(路径)来实现的,即描边绘制动画效果。可以看看以前的关于描边绘制动画效果入门文章。也可以看看下面这两篇文章的介绍:

Animated line drawing in SVG by Jake Archibald。

How SVG Line Animation Works by Chris Coyier。

这次我们使用的技术有点变化,一般这种秒变绘制动画都使用stroke-dashoffset这个属性来实现的,这次我们将使用stroke-dasharray来实现描边绘制动画效果。使用stroke-dasharray可以更加的灵活些,比如可以控制path(路径)的绘制方向。想知道更多的细节的话,可以去看看之前写的一篇文章

使用Pug来编写HTML

开始之前先使用Pug(它更出名的一个名字是Jade)这个高效的模板引擎来编写HTML,可以看看这篇入门教程

Pug的语法非常简单,就是使用诸如变量等特性来编写HTML。看下面的代码,你就知道是多么的简单了。

//- Background image and button
<div class="background-image"></div>
<button>Toggle Animation</button>

//- Some variables to help with maths
- var circlesNumber = 5;
- var strokeWidth = 150;
- var radius = 100;
- var width = radius * 2;
- var height = radius * 2;
- var left = width / 2;
- var top = height / 2;

//- The main function to build a circle (SVG path)
//- Formula taken from this answer: http://stackoverflow.com/a/10477334
mixin circle(className)
    <path class="#{className}" d="M #{left} #{top} m -#{radius} 0 a #{radius} #{radius} 0 1 0 #{radius * 2} 0 a #{radius} #{radius} 0 1 0 -#{radius * 2} 0"/>

//- Center circle
<svg class="svg-center" width="#{width}" height="#{height}">
    + circle('path-center')
</svg>

//- Reset some variables to build the other circles
- width = 10000;
- height = 5000;
- left = width / 2;
- top = height / 2;
- radius += strokeWidth / 2 - 1;

//- Very big SVG
<svg class="svg-borders" width="#{width}" height="#{height}">

    //- Build the circles, increasing the radius at each iteration
    while circlesNumber--
        + circle('path-borders')
        - radius += strokeWidth - 1;
</svg>

通过上面的代码,我们使用SVG path(路径)生成了一些圆圈,然后使用一些样式,来使这些圆圈足够大以便覆盖背景图片。

SVG path(路径)绘制动画

基本的结构准备好了,下面就使用SVG path(路径)来实现动画效果。代码如下:

// Same variables used in HTML
$circlesNumber: 6;
$strokeWidth: 150;
$radius: 100;

// PI value (approximately)
$pi: 3.15;

// A big length
$maxLen: 10000;

// Loop to generate convenient stroke-* values
@while $circlesNumber > 0 {

  // Calculate the SVG path length (approximately)
  $currentRadius: $radius + ($circlesNumber) * $strokeWidth - $strokeWidth / 2;
  $len: 2 * $pi * $currentRadius;

  // Draw the entire path
  .path-borders:nth-child(#{$circlesNumber}) {
    stroke-dashoffset: $maxLen;
    stroke-dasharray: $maxLen 0 $len;
  }

  .open-state {

    // "Erase" the path, with alternating direction
    .path-borders:nth-child(#{$circlesNumber}) {
      @if ($circlesNumber % 2 == 0) {
        stroke-dasharray: $maxLen 0 0;
      } @else {
        stroke-dasharray: $maxLen $len $len;
      }
    }
  }

  // Next iteration
  $circlesNumber: $circlesNumber - 1;
}

我们来看看编译之后输出的一段CSS动画代码:

.path-borders:nth-child(2) {
  stroke-dashoffset: 10000;
  stroke-dasharray: 10000 0 2047.5;
}

.open-state .path-borders:nth-child(2) {
  stroke-dasharray: 10000 0 0;
}

可以看到,如果使用CSS来编写,就要手动计算出每一个path(路径)的长度,还是有点工作量的。如果使用SCSS的话,就可以可以它提供的计算功能来自动计算每一个path(路径)长度就可以了,不需要一个个手动计算了。

一些动画细节

最后,为了使动画更加的细腻,需要打磨一些动画细节。

.open-state {

  // Scaling down the image
  .background-image {
    transform: scale(1);
  }

  // Rotating SVG paths (except the center circle)
  .svg-borders {
    transform: translate(-50%, -50%) rotate(90deg);
  }

  // Animating the center circle
  .path-center {
    stroke-width: 400px;
  }
}

一个酷炫的页面过渡动画效果就完成了。demo体验地址

更多的代码细节,可以去github上看看

本文主要是从Creative Splash Transition with CSS and SVG这篇文章整理而来,有删减,有疏漏或者理解不到位的地方,还请多多指教!