这是个人一个关于SVG的应用的技术分享网站svgtrick.com,会同步一些文章到这里来,更多关于SVG技术应用能够去网站看看。javascript
最近从Dribbble shot 看到@thorstenbeeck发布的一个设计效果图获得灵感。根据这个设计,使用GreenSock这个动画平台实现了一个SVG的动画效果,下面就来聊聊我是怎么实现这个动画效果的。html
GreenSock是一个无需多介绍了,是一个专门用来开发动效的平台,而且提供了javascript版本。更多关于GreenSock的一个入门介绍能够去我整理的简明教程看看,这里就再也不介绍它的基本知识。java
GreenSock在制做SVG动画方面也很是强悍,而且还专门提供了用于增强SVG动画制做的相关插件,好比Greensock DrawSVG plugin。它能够实现任何SVG图形的绘制,也能够操做诸如stroke-dashoffset和stroke-dasharray等CSS属性来制做一些描边的动画效果,下面来一个简单的实例:express
详细代码地址canvas
这一步将使用SVG来实现Dribble shot上的效果图。从效果图能够看到整个图形都是由简单的一些几何图形组成的,而绘制图形正是SVG所擅长的,使用SVG来实现这样的形状很是简单。app
首先来为整个图形建立一个画布。建立一个SVG元素。而后建立一个跟画布同样大的矩形元素 rect 而后使用一个圆形的 clipPath 元素来遮住整个画布使其内容只显示在圆形的遮罩内。代码以下所示:svg
<svg viewBox="0 0 500 500"> <g class="canvas"> <defs> <clipPath id="circle"> <circle class="mask" cx="250" cy="250" r="100" /> </clipPath> </defs> <g clip-path="url(#circle)"> <rect class="bg" x="0" y="0" width="500" height="500" /> </g> </g> </svg>
一个基本的布局就完成了。下面是来添加一些样式。固然你可使用行内样式或者是内联样式也能够是外链样式。工具
<circle class="mask" cx="250" cy="250" r="100" fill="red" /> <circle class="mask" cx="250" cy="250" r="100" style="fill: red;" />
通常样式建议使用外链的方式来引入样式,这样能够保证html的整洁以及可维护性。固然也可使用诸如SASS等预编译语言来编写CSS,能够利用预编译语言提供的变量功能来管理颜色或者是字号等全局样式,很是方便。布局
因为我使用的是SASS,我把颜色都在SASS中定义好对应颜色名称的变量里面:学习
// Color palette $red: #E9214F; $burnt-sienna: #F06B4B; $goldenrod: #F6DA71; $scooter: #349597; $midnight-express: #20283B; $marzipan: #FCDC9F; $fruit-salad: #49934E; $goblin: #3D7C42; $chambray: #44557E; $port-gore: #384668; $white: #ffffff; $silver-sand: #BBBBBB; // Set background color body { background-color: $midnight-express; } // Center the svg horizontally and vertically svg { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 500px; height: 500px; backface-visibility: hidden; } // Color styles .canvas { .bg { fill: $scooter; } .ground { fill: $marzipan; } .sky1 { fill: $goldenrod; } .sky2 { fill: $burnt-sienna; } .sky3 { fill: $red; } .tree-left { fill: $fruit-salad; } .tree-right { fill: $goblin; } .mountain-left { fill: $chambray; } .mountain-right { fill: $port-gore; } .mountain-top-left { fill: $white; } .mountain-top-right { fill: $silver-sand; }
如今整个是静态的,咱们使用一点点GreenSock代码来实现一个从小到大缩放动画效果:
// 定义好要操做相关元素的变量 const svg = document.querySelector('svg') const canvas = { wrapper: svg.querySelector('.canvas'), mask: svg.querySelector('.canvas .mask') } // 建立一个新的GASP的时间轴 const tl = new TimelineMax({ repeat: -1 }) // 使用 GASP的from方法来定义mask元素半径从0到1的缩放动画效果 tl.from(canvas.mask, 1, { attr: { r: 0 }, ease: Elastic.easeOut.config(3, 1) })
几行代码,一个缩放的动画效果就完成了:
接下来是绘制天空和地面元素。使用SVG中的矩形元素 rect 来绘制,三个用来绘制天空一个用来绘制地面:
<svg viewBox="0 0 500 500"> <g class="canvas"> <defs> <clipPath id="circle"> <circle class="mask" cx="250" cy="250" r="100" /> </clipPath> <clipPath id="ground"> <rect x="50" y="50" width="400" height="260" /> </clipPath> </defs> <g clip-path="url(#circle)"> <rect class="bg" x="0" y="0" width="500" height="500" /> <g clip-path="url(#ground)"> <rect class="sky3" x="50" y="130" width="350" height="70" /> <rect class="sky2" x="50" y="200" width="350" height="50" /> <rect class="sky1" x="50" y="250" width="350" height="50" /> </g> <rect class="ground" x="100" y="300" width="350" height="10" /> </g> </g> </svg>
一样这里也须要为它们增长一点动效,首先是地面的动效,地面的动效是从下往上冒出的。
tl.from(canvas.ground, 0.5, { autoAlpha: 0, attr: { y: '+=200' }, ease: Power4.easeOut }, 0.1)
天空的动效跟地面同样的。因为天空有3个元素,而且是依次出现而不是同从下往上冒出来,可使用GreenSock中的 stagger 方法来实现:
tl.staggerFrom([canvas.sky1, canvas.sky2, canvas.sky3], 0.5, { autoAlpha: 0, skewY: 0, attr: { y: '+=90' }, ease: Elastic.easeOut.config(1, 3) }, 0.075, 0.25)
为了使动画更加细腻,作完动画后还须要调整下动画的运动曲线,可使用GreenSock提供的一个可视化动画曲线调整工具来选择合适的动画曲线 ease visualizer。
下面添加地面上的树,树由两个三角形组成。由于数是一个一个挨着排列的,因此使用 g 元素来包裹树元素编成一个组,这样方便来布局:
<g class="tree tree1" transform="translate(150 255)"> <polygon class="tree-left" points="15,0 15,50 0,50" /> <polygon class="tree-right" points="15,0 15,50 30,50" /> </g>
重复复制七份一样的代码,而且使用transform来改变树的位置,从而使之依次排列。而后是使用GreenSock来编写树的动画效果,树的动画效果是从45度旋转到0度旋转的效果而且同时从0到1的缩放效果:
tl.staggerFrom([canvas.tree1, canvas.tree2, canvas.tree3, canvas.tree4, canvas.tree5, canvas.tree6, canvas.tree7], 0.5, { rotation: 45, scale: 0, transformOrigin: 'bottom center', ease: Back.easeOut.config(2, 1.55) }, 0.05, 0.4)
效果以下所示:
最后是后面的大山以及大山的动画效果。
大山由四个三角形元素组成,代码以下:
<g class="mountain" transform="translate(150 185)"> <polygon class="mountain-left" points="100,0 100,120 0,120" /> <polygon class="mountain-right" points="100,0 200,120 100,120" /> <polygon class="mountain-top-left" points="100,0 100,30 75,30" /> <polygon class="mountain-top-right" points="99,0 125,30 99,30" /> </g>
它的动画效果和树的效果差很少,只不过是把旋转的动效变成翻转的效果。
tl.staggerFrom([canvas.mountain], 0.75, { y: '+=50', skewX: -200, scale: 0, transformOrigin: 'bottom center', ease: Back.easeOut.config(1, .2) }, 0.0125, 0.5)
一个有趣的SVG的动画效果就完成了,代码地址使用GreenSock 配合 SVG 来制做动画效果如此简单。
原文地址,根据本身理解整理了下这个教程,主要是来学习下使用GreenSock来制做SVG动画效果的思路和方法。