SVG动画应用-酷炫的图片展示效果

2,697 阅读4分钟

偶然在svgTrick上看到了一个效果,模仿了一下。作者原先也是受到dribble上的一个动效启发,这个效果与svg简直是天作之合。

最后模拟的效果如下,gif有点卡顿,戳戳这里查看网页效果

做一个酷炫的svg整体效果

我们先看着动效分析一下,主要可以将动画分成五部分。

  • 中心圆从圆心开始消失
  • 多个环状进度动画
  • 环状整体的旋转动画
  • 白色描边动画
  • 其他文案动画

一个个对照来看:

中心圆从圆心开始消失

这个效果的完成很简单。只需要在画面正中间画一个svg,svg上是一个顶着边的圆,因为svg的描边是由中间向两侧描边的,控制描边的宽度从填满到0就可以实现我们想要的效果啦。

这里我们画的是一个半径为100的圆,也就是用描边完全填满的宽度需要200。注意控制border-radiusoverflow,使超出区域不可见。

<svg class="svg-center" viewBox="0 0 200 200">
    <path class="path-circle" d="M 0 100 A 50 50 1 0 1 200 100 A 50 50 1 0 1 0 100" stroke="#1e1e1e" fill="none" />
</svg>
.svg-center{
  border-radius: 50%;
  overflow: hidden;
  stroke-width: 200;
}
@keyframes svgCenter{
    0%{
        stroke-width: 200;
    }
    100%{
        stroke-width: 0;
    }
}

多个环状进度动画

这其实就是我们常见的进度条动画,虽然这个环看起来很粗,不像一条边,但是实际上这也是一个经典的描边动画。

<svg class="svg" viewBox="0 0 1000 1000">
    <g class="wrap-path" fill="none" stroke="#1e1e1e" stroke-width="60">
      <path class="path-1" d="M 420 500 A 50 50 1 0 1 580 500 A 50 50 1 0 1 420 500"/>
    </g>
  </svg>
.path-1{
    stroke-dasharray: (80 * 3.15 * 2)  (80 * 3.15 * 2);
    animation: path1 1s both;
}
@keyfraes path1{
    0%{
        stroke-dashoffset: 0;
    }
    100%{
        stroke-dashoffset: (80 * 3.15 * 2);
    }
}

因为这里的svg的viewBox一开始定义的是1000*1000,最后我们会把它同比例放大两倍处理,所以在原画布中,中间需要镂空出50半径的圆形区域,另外还是根据描边是像两侧描边的设定,所以实际上我们画的是一个半径为80的圆,描边宽度为60。

多个圆的情况下因为需要得到dasharray等值,一个个计算比较麻烦,可以用scss函数进行编译。对于scss函数编译不熟悉的,推荐使用sassmeister这款在线编译工具,可以实时看到编译结果。

$pathNums: 7 !default; 
$time: 1s !default;
$$cubic-bezier: cubic-bezier(0.77, 0, 0.175, 1);

@for $i from 1 through $pathNums {
    .path-#{$i} {
        stroke-dasharray: ((60 * $i + 20)  * 3.15 * 2)  ((60 * $i + 20)  * 3.15 * 2);
    }
    @if $i%2 == 0{
        $offsetType: 1;
    }@else {
        $offsetType: -1;
    }
    <!-- 动画 -->
    @keyframes path#{$i}{
        0%{
            stroke-dashoffset: 0;
        }
        100%{
            stroke-dashoffset: ((60 * $i + 20)  * 3.15 * 2) * $offsetType;
        }
    }
}
.wrap-container.animation{
    @for $i from 1 through $pathNums {
        .path-#{$i} {
        animation: path#{$i} $time $cubic-bezier both;
    }
  }
}

本来打算把path路径也通过函数的方式直接循环定义,但是因为scss编译会自动在冒号后加空格,导致d:path()识别错误,所以这里还是直接在html中定义path。遇到复杂的路径同样可以使用scss函数在线编译,再复制到html中,减少人工计算的量和错误率。


环状整体的旋转动画

这个利用css的transform:rotate()即可完成,我们将多个环编组,从0旋转90°即可。

<svg class="svg" viewBox="0 0 1000 1000">
    <g class="wrap-path" fill="none" stroke="#1e1e1e" stroke-width="60">
    </g>
</svg>
.wrap-path{
    animation: pathRotate 1s both;
}
@keyframes pathRotate {
    0%{
        transform: rotate(0);
    }
    100%{
        transform: rotate(90deg);
    }
}

白色描边动画

白色描边动画除了在原先的环状动画+整体的旋转之外,我们能看到它基于整体还有自己的一个旋转,加上即可,显得白色描边速度比整体快,丰富了动画的层次感。这样整体的动画效果就呈现出来啦。


其他文案动画

这里暂时只加了一个背景中间文案的缩放动画,造成一种视差错觉。

菠萝小结

  1. 注意描边的特点是从中间向两侧扩展;
  2. 环形进度条动画也是描边动画;
  3. 同时运用多种效果/方向/速度,可以丰富动画的层次感。