WarpPrism / Blog

Do Epic Things
52 stars 7 forks source link

svg系列:2. svg path实现图片路径动画 #35

Open WarpPrism opened 6 years ago

WarpPrism commented 6 years ago

为了之后产品可能的动画需求,我们需要调研各种可行的前端动画技术。相信CSS3动画和JS动画我们平常已经接触很多了,而SVG技术则很少用,事实上SVG也是一种强大的动画解决方案,可以帮我们解决传统动画做不到的技术痛点。

SVG简介

SVG文件可单独使用,使用XML定义并包含DTD声明:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <circle cx="100" cy="50" r="40" stroke="black"
  stroke-width="2" fill="red" />
</svg>

在现代浏览器中,我们可以直接在HTML代码中嵌入SVG代码:

<div class="svg-wrap">
  <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
     <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
  </svg>
</div>

SVG path

SVG可以绘制许多形状,这里不一一介绍,重点介绍下svg path,它是svg形状中功能最为强大的一个,也是我们前端动画会经常用到的形状。

顾名思义,path定义的是一组路径,你可以用path元素绘制矩形(直角矩形或者圆角矩形)、圆形、椭圆、折线形、多边形,以及一些其他的形状,例如贝塞尔曲线、2次曲线等曲线。path元素的形状是通过它的 d 属性决定的,d属性中通常以字母为命令,如下所示:

M = moveto
L = lineto
H = horizontal lineto
V = vertical lineto
C = curveto
S = smooth curveto
Q = quadratic Bézier curve
T = smooth quadratic Bézier curveto
A = elliptical Arc
Z = closepath

以下path 定义了一个三角形:它开始于位置150 0,到达位置75 200,然后从那里开始到225 200,最后在150 0关闭路径。

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
    <path d="M150 0 L75 200 L225 200 Z" />
</svg>

注意:绘制复杂的path路径应尽可能借助设计工具,人为计算path的d属性耗时耗力,也不是目前的学习重点。

path的其他常用属性有:

基于svg path实现图片路径动画

点击这里查看demo:

WPS Logo Demo

这个效果的实现并不复杂,首先我们需要wps logo的svg资源,可以借助photoshop 和 Adobe Illustrator 从图片中生成svg路径。

第一步,使用ps魔棒工具去除白色背景,并选中路径,然后右键,建立工作路径:

点击菜单-> 文件 -> 导出 -> 导出路径到ai :

在ai中选中路径,存储为svg格式。然后在编辑器中打开svg即可查看到path的d属性了!

之后,在代码里创建svg图形,并指定其stroke-width等属性。

动画方面,使用css animation控制path的stroke-dasharray属性来实现动画,这个属性可以将path绘制为虚线。

stroke-dasharray: 10px 20px; 就定义了实线的长度是10px,空白的长度是20px,如下图所示:

dash

利用这个原理,我们将实线的长度从0逐渐变为path总长度,将空白的长度逐渐变为0,就可以实现类似“绘图”的效果了~

#wps-logo-path {
  animation: wpsLogo 3s ease-in-out forwards;
}

@keyframes wpsLogo {
    0% {
        stroke-dasharray: 0 1078px;
    }
    100% {
        stroke-dasharray: 1078px 0;
    }
}

path的总长度可以这样计算 $('#wpsLogoPath')[0].getTotalLength()

动画过程中,可以设置监听,在动画的不同阶段执行不同的钩子函数:

document.addEventListener('webkitAnimationEnd', function(e) {

}

代码中,我们还定义了线性渐变,用来填充path闭合区域内的背景值,fill: url(#wpslinear)

<defs>
  <linearGradient id="wpslinear" x1="0%" y1="0%" x2="0%" y2="100%">
    <stop offset="0%" stop-color="#FB5A43"/>
    <stop offset="100%" stop-color="#FD3258"/>
  </linearGradient>
</defs>

到这一步,svg path动画的demo就基本做完了,我们可利用这个原理实现更复杂的svg path动画,如多个path的过渡动画,物体沿不规则path移动等等。svg技术本身还是很复杂的,短时间掌握svg有一定的难度,必要时可以借助svg动画库实现需要的设计效果,做到技术灵活服务于产品。