SVG动画从入门到实战,提升你的网站表现力

在 SVG 中,如果我们想实现一个动画效果,可以使用 CSSJS,或者直接使用 SVG 中自带的 animate 元素(SMIL)。

这里我们主要探讨SVG与CSS结合实现的一些常见动画效果。

(下面要使用到的SVG基础知识,在 SVG从入门到图标绘制和组件封装SVG中的Transform详解---平移、旋转和缩放 中都有详细的介绍,这里就不重复了,有需要的朋友可以前往查看哦。 )

SVG + CSS 动画实现的基础

HTML5 支持内联 SVG,我们可以将SVG元素作为html标签的一种,直接在页面结构中使用,成为 DOM 的一部分,这也使得我们可以用 CSS 对其做样式开发,这也是SVG + CSS 动画实现的基础。


   

上面的代码片段在页面绘制一个宽高100px的金色正方形。这里使用标签属性的方式描述它的宽度、高度和填充色,其实我们也可以在CSS中写这些样式。


   
rect{
   width: 100px;
   height: 100px;
   fill: gold;
}

既然能用CSS对SVG做样式开发,那么结合animationtransitiontransform,使SVG元素的样式进行动态变换,就可以达到我们想要的动画效果。

rect{
   width: 100px;
   height: 100px;
   fill: gold;
   transition: fill 1s linear;
}
rect:hover{
   fill: greenyellow;
}

SVG动画从入门到实战,提升你的网站表现力_第1张图片

基于transform的形状变换动画

和普通的HTML元素一样,SVG元素可以通过transform进行平移、旋转和缩放等形状变换。

但两者的变换参考点不同。对于普通的HTML元素,变换的参考点,默认值是元素自身在x、y方向的中心位置50% 50%(这里仅考虑二维平面),也就是元素的旋转、移位、缩放等操作都是以元素自身在x、y方向的中心位置进行的。

而SVG元素,变换的参考点,是在SVG画布的0 0的位置(默认是元素的左上角)。

SVG动画从入门到实战,提升你的网站表现力_第2张图片

理解这一点对于理解SVG元素的transform变换非常重要,我们在前面的两篇文章中进行了非常详尽的讲解:

SVG从入门到图标绘制和组件封装

SVG中的Transform详解---平移、旋转和缩放

仿B站直播图标

动画实现


    
    
    

使用标签绘制三条竖直的线条,(x1,y1)是线条起始点的坐标,(x2,y2)是线条终点的坐标。

SVG动画从入门到实战,提升你的网站表现力_第3张图片

(为了方便观察,我们给svg设置一个蓝色边框。)

接着,通过keyframes动画,不断改变scaleY,让线条在Y方向进行缩放。

.beat{
    transform-origin: bottom;   //将变换参考点设置成`元素`的底部
    animation: beat-scale 1.4s linear infinite;
}
        
@keyframes beat-scale{
    25%{
         transform: scaleY(0.3);
    }
    50%{
         transform: scaleY(1);
    }
    75%{
         transform: scaleY(0.3);
    }
}

SVG动画从入门到实战,提升你的网站表现力_第4张图片

最后,通过设置animation-delay,让三段线条交错运动。

.beat:nth-child(1){
    animation-delay: 0.4s;
}
.beat:nth-child(2){
    animation-delay: 0.2s;
}

SVG动画从入门到实战,提升你的网站表现力_第5张图片

组件封装

实现了动画,接下来就是把图标进行组件封装,以便一次定义,多处引用。

参考:SVG组件封装

两个改造点:

  • 1、将标签都放到中,标签设置viewBox="0 0 100 100"
  • 2、将stroke="lightblue"改成stroke="currentColor",在使用svg图标时,颜色就会从父元素的color属性继承。

    
      
          
          
          
      
    

    使用:

    
      
              
      
      直播中
    

    SVG动画从入门到实战,提升你的网站表现力_第6张图片

    加载时钟

    
     
     
     
    

    标签绘制时钟轮廓,两个绘制长针和短针。

SVG动画从入门到实战,提升你的网站表现力_第7张图片

长短针的旋转,我们希望绕图标自身中心点进行。

我们知道,SVG元素变换的参考点,是在SVG画布的0 0的位置。那么如果图标的中心点SVG画布0 0的位置重叠,那图标岂不就绕自身中心点进行旋转。

因此,我们将标签圆心坐标设为(0,0)(cx="0" cy="0"),同时长短针的起点坐标也设为(0,0)。为了图形显示完全,设置元素的viewBox属性为"-52 -52 104 104"

SVG动画从入门到实战,提升你的网站表现力_第8张图片

动画的实现就是通过keyframes动画,不断改变长短针的rotate角度,由于两者旋转速度不同,所以动画时间设置不同。

.fast-hand{
   animation: clock-rotate 2s linear infinite;  /*动画时间设置不同*/
}
.slow-hand{
   animation: clock-rotate 15s linear infinite;  /*动画时间设置不同*/
}
@keyframes clock-rotate{
   0%{
        transform: rotate(0deg);
   }
   100%{
        transform: rotate(360deg);
   }
}

SVG动画从入门到实战,提升你的网站表现力_第9张图片

封装成组件的代码和使用案例如下:


   
       
       
       
   

等待中

SVG动画从入门到实战,提升你的网站表现力_第10张图片

描边动画

常用 SVG + CSS 来实现的,除了transform + animation/transition这种组合实现图标的形状变换动画,另一种用处非常广泛的就是描边动画。

stroke-dasharray & stroke-dashoffset

描边动画的核心是 SVG 的两个显示属性,分别是 stroke-dasharraystroke-dashoffset

stroke-dasharray用于创建虚线。它的值是一个序列,可以传入多个值,分别指定虚线中线段和间隔的长度。

stroke-dasharray = '10, 20' 表示:线段10,间距20,然后重复 线段10,间距20。。。

该参数序列可以是一到多个数值,当数值的个数为奇数时,会自动复制一份,再生效。

比如stroke-dasharray = '10'相当于stroke-dasharray = '10, 10'

stroke-dasharray = '10, 20, 30'相当于stroke-dasharray = '10, 20, 30, 10, 20, 30',此时的绘制规则是:线段10,间距20,线段30,间距10,线段20,间距30,然后重复。。。

SVG动画从入门到实战,提升你的网站表现力_第11张图片
stroke-dashoffset: 描述相对于起始点的偏移。它的值是一个数值X,X>0时,相当于往左移动了X个长度单位; X<0时,相当于往右移动了X个长度单位。

stroke-dashoffset只有在设置了stroke-dasharray的情况下,才生效,非虚线的话,是无法看出偏移的。

SVG动画从入门到实战,提升你的网站表现力_第12张图片

对于一条线l,如果设置stroke-dasharray = 'l.length',那么显示出来的就只有线段,没有间隔,相当于实线效果。而此时如果stroke-dashoffset='l.length',那线l就往左移动了l.length个长度单位,显示出来的就只有间隔,没有线段,相当于空白的效果。

如果stroke-dashoffset的值从l.length-->0,线段就会逐渐显示出来。从而产生描边的效果。

SVG动画从入门到实战,提升你的网站表现力_第13张图片

描边效果的动画在开发中有很多应用场景,比如各种形状的进度条,图标或文字的描边,以及一些酷炫的按钮边框动画等。

案例实现

环形进度条

首先,我们将stroke-dasharraystroke-dashoffset都设为圆环的周长;然后根据进度progress计算动态计算出新的stroke-dashoffset,即(1-progress) * 圆环的周长

计算圆环周长的方法:

  • 1、在已知半径的情况下,可以根据公式2*Pi*r求得周长。
  • 2、SVG的形状元素都有一个getTotalLength的方法,可以获取该形状的路径总长度,对于规则和不规则的形状都适用。

    //页面结构
    
    调整进度:
    //js代码,获取圆环周长,并在调整进度后改变蓝色圆环的stroke-dashoffset
    
    //css代码
    .progress{
      display: inline-block;
      position: relative;
    }
    .progress::before{
      content: attr(data-percent);
      position: absolute;
      width: 100%;
      top: 50%;
      left: 0;
      transform: translateY(-50%);
      font-size: 20px;
      text-align: center;
    }
    .progress::after{
      content: attr(data-name);
      position: absolute;
      width: 100%;
      top: 100%;
      left: 0;
      font-size: 25px;
      text-align: center;
    }
    .process-circle{
      stroke-dashoffset:251;
      transition: stroke-dashoffset 3s;
    }       
    .adjust{
      margin-top: 50px;
    }

    环形加载动画

    stroke-dashoffsetanimation结合还可以实现环形的加载动画,这是一种非常常见的加载动画。
    SVG动画从入门到实战,提升你的网站表现力_第14张图片

    
      
      
      
      
    
    .progress{
      stroke: #F7C223;
      animation: move 2s linear infinite;  
    }
    .container{
      animation: container 2s linear infinite;      
    }
    //给外框也加上旋转动画,两个旋转叠加,效果更自然
    @keyframes container {
      0% { transform: rotate(0deg); }
      100% { transform: rotate(270deg); }
    }    
    @keyframes move{  //在改变stroke-dashoffset的同时也让圆环旋转
      0%{
          stroke-dashoffset: 251px;
      }
      50%{
          stroke-dashoffset: calc(251px * 0.2);
          transform:rotate(135deg);
      }
      100%{
          stroke-dashoffset: 251px;
          transform:rotate(450deg);
      }
    }

    还可以再加上变色的动画,效果更绚丽。

SVG动画从入门到实战,提升你的网站表现力_第15张图片

.progress{
    stroke: #F7C223;
    animation: 
         move 2s linear infinite,
         color-change 2s linear infinite;
}
@keyframes color-change {
    0% { stroke: #4285F4; }
    25% { stroke: #DE3E35; }
    50% { stroke: #F7C223; }
    75% { stroke: #1B9A59; }
    100% { stroke: #4285F4; }
}

文字描边

以描边动画的方式出场可以使人对logo或者文字的印象更加深刻。


    
        
        
        
        
        
    

这里每个字母都是由path元素绘制的图标,这种比较复杂的图形一般是由设计软件绘制,然后生成svg代码,我们这里使用的是figma。

对于这种不规则图形,只能用getTotalLength方法可以获取该形状的路径总长度,然后设置stroke-dasharraystroke-dashoffset的值。

const words = document.querySelectorAll('path')
for(let i=0; i

SVG动画从入门到实战,提升你的网站表现力_第16张图片

body{
    background: #2e4057;
    display: flex;
    justify-content: center;
    align-items: center;
}
svg{
    stroke: hsl(189, 68%, 75%);
    stroke-width:1px;
    fill:hsl(189, 68%, 75%, 0%);
    animation: color-change 1s ease-in forwards 3.8s;
}
//每个字母的描边动画执行时间和开始时间不同
path:nth-child(1){
    stroke-dasharray: 246;
    stroke-dashoffset: 246;
    animation: show 1s linear forwards;
}
path:nth-child(2){
    stroke-dasharray: 253;
    stroke-dashoffset: 253;
    animation: show 1.2s linear forwards .5s;
}
path:nth-child(3){
    stroke-dasharray: 334;
    stroke-dashoffset: 334;
    animation: show 1.4s linear forwards 1s;
}
path:nth-child(4){
    stroke-dasharray: 246;
    stroke-dashoffset: 246;
    animation: show 1.6s linear forwards 1.5s;
}
path:nth-child(5){
    stroke-dasharray: 240;
    stroke-dashoffset: 240;
    animation: show 1.8s linear forwards 2s;
}
@keyframes show{
     to{
           stroke-dashoffset: 0;
     }
}
@keyframes color-change{
     to{
           stroke: transparent;
           fill:hsl(189, 68%, 75%)
     }
}

按钮hover效果

SVG动画从入门到实战,提升你的网站表现力_第17张图片

非hover状态:stroke-dasharray: 170 540,线段和间隔分别为170和540;stroke-dashoffset: -459表示相对于起始点(矩形左上角)向右偏移(顺时针偏移)459,此时线段绘制在文字的正下方。

hover状态:stroke-dasharray: 760,760为矩形的周长,此时stroke-dashoffset: 0不偏移,绘制效果为一个完整的矩形。


    
Check it!
html, body {
    background: #333;
    height: 100%;
    overflow: hidden;
    text-align: center;
}
.wrapper {
    height: 60px;
    margin: 0 auto;
    position: relative;
    top: 50%;
    transform: translateY(-50%);
    width: 320px;
}
.border-rect {
    fill: transparent;
    stroke-dasharray: 170 540;
    stroke-dashoffset: -459;
    stroke-width: 8px;
    stroke: #d20be4;
    transition: all linear 0.5s;
}
.text {
    color: #fff;
    font-family: 'Roboto Condensed';
    font-size: 22px;
    letter-spacing: 8px;
    line-height: 32px;
    position: relative;
    top: -48px;
}
.wrapper:hover .border-rect {
    stroke-dasharray: 760;
    stroke-dashoffset: 0;
    stroke-width: 2px;
}

总结

本文主要探讨了SVG结合CSS实现动画的基础,以及一些常见动画的实现方式。随着浏览器对web标准支持的越来越好,SVG的使用也越来越方便,在做网站交互的时候,可以适当使用SVG动画提升你的网站表现力。

你可能感兴趣的:(SVG动画从入门到实战,提升你的网站表现力)