手把手教你使用 SVG 实现手写 (路径) 动画效果

6,039 阅读10分钟
原文链接: svgtrick.com

这篇文章来教你如何使用GreenSock一步一步的来实现一个手写的动画效果。

要实现这样的效果主要有两部分的工作要做,一部分使用Adobe Illustrator等矢量设计工具来设计好你需要手写动画效果的文字的路径。比如上面这个效果就需要handwriting这个单词的路径。

下面就跟着我一步一步从零开始实现手写的动画效果。

找字体

首先,找好你喜欢的一种字体,我这里使用的是HaloHandletter Bold。这个字体的效果还不错,并且是一个等宽字体。如果你使用的是不等宽的字体,可能就需要用到遮罩的方法来实现等宽。字体效果如下所示:

你可能会认为使用它来得到字体的轮廓会非常简单。

但实际上这样的路径并不是我们想要的。当然,在一些场景下,我们可能想要的效果就是先把文字的轮廓绘制出来然后再填充文字。不过,手写的动画效果需要的路径不是这样的。

使用钢笔工具

在文字图层上新建一个图层用来绘制路径,我一般喜欢把文字的背景设置为深色的,这样可以方便后面用钢笔来绘制路径。

我们需要得到文字的路径,使用钢笔工具再方便不过了。双击钢笔工具然后把钢笔的笔触的平滑度调到右边的最大值。

接下来就是整个效果中最花功夫的,对着文字图层使用钢笔工具在新建的图层上重新把文字绘制一次。在绘制的时候,一定要记得曲线要平滑,特别是在拐角的地方。对于这个handwriting这个单词,我主要分为四部分来绘制。H这个字母要分成两段,中间部分分成一段路径,最后的T字母也占用一段路径。

在绘制的时候,不要一次就绘制好,你可以绘制一段停下来,放大细节看一看,然后再接着绘制。这样可以保证绘制出来的路径符合我们的要求。需要提醒一点的是,在绘制路径的时候,要尽可能模拟人在写文字时候的感觉,比如有时候在写字的时候,可能需要在同一个地方写两次。

接下来对自文字来调整路径,使其和文字匹配上。开始调整之前,建议填充路径边框并且把路径图层的透明度调整为75%,这样可以直接通过路径看到底下的文字图层,然后选择一种路径边框的填充颜色,我选的是绿色,在最后编写动画效果的时候,可以随时调整。在这个例子中,我设置路径边框的宽度是10px除来第一个字母H设为14px,这个主要是跟你选择的字体有关。

绘制完之后,可能有些路径会存在很多的尖角存在,修复也很简单。

对那些尖角,可以使用圆角这个控件来修复。使用路径直接选择工具,然后在有尖角的路径的地方点击路径上的控制点,你会在控制点的下方看到一个白色的空心圆圈,双击它就可以调出圆角的控件,设置圆角的大小就可以把尖角变成圆角,通过拖拽可以调整它的位置。

经过调整后,就得到了需要的路径。至于怎么使用钢笔和贝塞尔工具来调整曲线,这里就不再详细的说了,网络上有很多这方面的资源。

整个动画效果的实现最花时间就是路径绘制这一部分。对于使用AI的老手来说,也许只要几分钟就可以完成;对于一个AI新手来说,可能就要花费大部分的时间在这上面,一个小时或者是更多的时间。对于工具来说,只能是多加练习了,熟能生巧。

至于路径和文字的匹配度,只要足够的接近就可以了,不一定要100%的匹配。

下面就是最终绘制出来的路径和原文字图层的一个对比:

最花时间的一部分工作做好了,接下来就是动画部分的工作。在开始编写动画代码之前,把每一段路径都分配一个class,方便后面操作,这里推荐使用GreenSockTweenMaxDrawSVGMorphSVG来完成这个动画效果。

接着往下看。

使用GreenSock实现手写动画

完成了路径的绘制后,接下来使用GreenSock来实现手绘的动画效果。

开始之前,先介绍下要用的TweenMax和其它的两个插件。

1、DrawSVG:这个插件主要用来实现路径绘制动画效果的。当然,你也可以使用JavaScript来实现绘制动画效果,但是使用这个插件可以解决浏览器兼容性问题,并且还提供了很多功能来更好的控制路径的绘制。

2、MorphSVG:从插件的名字就可以知道它使用来实现SVG形变动画用的,它还提供了一个非常有用的方法MorphSVGPlugin.pathDataToBezier(),使用它可以实现元素跟随路径运动的动画效果。用它我们就可以实现用笔书写文字的动画效果。

当然,这两个插件都是收费的,需要加入到Club GreenSock才能使用它,不过你可以在CodePen上免费使用它来做一些练习,可以看看这个demo合集

绘制路径

使用DrawSVG插件可以非常方便实现路径绘制动画效果,比如一段这样的路径:

 <path id="path1" d="M169.2,107c-.71,70.36,47.26,138.58,113.71,161.71s146.42-.56,189.55-56.15c17.44-22.48,29-49,45.37-72.22s40-44.08,68.32-46.44c24.27-2,47.89,10,66,26.36s31.74,36.83,46.67,56.07c25.95,33.43,56.77,64,94.37,83.42s82.7,26.77,122.9,13.54,73.74-49.21,77.86-91.33" fill="none" stroke="#fff" stroke-linecap="round" linejoin="round" stroke-miterlimit="10" stroke-width="4"/>

只需要一行代码就可以实现一个路径绘制的动画效果:

TweenMax.fromTo("#path1", 1,  {drawSVG:"0% 0%"}, {drawSVG:"0% 100%"});

就是这么简单,实现手写文字的动画效果也一样,一行足矣。可以使用TweenMax提供的时间轴功能(timeline)来依次绘制每一段路径,来实现手写的效果。不过,如果我们还想使手写动画更加真实一点,比如有一只铅笔在路径绘制的时候,跟随路径一起运动改怎么做呢?如果是在以前,可能要花很多的时间来实现这个效果,不过,现在容易多了。

跟随路径运动

使用MorphSVG插件提供的MorphSVGPlugin.pathDataToBezier()方法实现路径跟随运动就变得非常简单了。首先需要把要跟随的路径就是在上面已经定义好的path1这段路径,使用MorphSVGPlugin.pathDataToBezier()定义好:

var motionPath1 = MorphSVGPlugin.pathDataToBezier("#path1", {align: "#target"});

然后使用TweenMax中to的方法中的bezier属性来调用上面使用MorphSVGPlugin.pathDataToBezier()定义好的路径来实现路径跟随运动:

// in this case, our target is a simple circle, but you can use anything 
// including groups or images... well, anything...
TweenMax.to("#target", 3, { bezier:{values:motionPath1, type:"cubic"}})

现在可以把路径绘制和路径跟随运动的效果合并起来,实现路径绘制跟随动画。在这个例子中,可以看到一个圆圈分别绘制了两条路径,并且都是跟随路径的轨迹一起运动的。可以看到使用GreenSock可以很轻松的实现这样的动画效果。

额外的位置数据

通过上面的一个小例子,明白了实现路径跟随和绘制动画的原理。但是从第一段路径到第二段路径之间绘制的时候,圆圈移动的时候是有一个补间的效果。这里需要额外定义铅笔跟随路径的一些位置数据,那怎么来确定路径起始点的位置呢? 其实一点也不复杂,只不过是下一段路径开始的起点的位置,比如第一段路径绘制完后,需要移动第二段路径绘制的起点,而不是突然跳到第二段路径开始绘制,所以这里需要加一个补间的效果。

坐标点从哪来呢?可以在控制台输出下定义好的两段路径路径的数据,就可以知道路径起点的坐标了:

// this will give us the array of points in the motion path
console.log(motionPath2);

// open the array and we'll see several objects
// check out the first one and you'll see the coordinates we need
// you should see something like this
0:Object
x:160.52
y:479.74

只需要把圆圈移动的坐标这一步骤加入到动画序列中,就可以使圆圈移动的时候有一个补间的动画效果。同理,文字的书写动画效果也可以这样做,当铅笔绘制完第一段路径的时候,开始绘制第二段路径的时候,用上面的方法使铅笔移动有一个补间的动画效果。

无论你有多少条路径,使用上面的方法,都可以使它过度的很自然。从上面圆圈跟随路径的例子中,你会注意到我在圆圈绘制完第二段路径的时候,马上移动到第一段路径的起点,这样就可以实现一个循环绘制的动画效果。

收尾

所有的准备工作都做好了,下面就是最后的收尾工作实现手写动画效果。只需要按照上面的方法的把对应的数据填充进去,就可以完成手写动画的效果。

分别定义好四条路径,获取第二段路径的起点的坐标,放到动画序列中:

TweenMax.set("path", {drawSVG:0});// set all path strokes to 0
var tl = new TimelineMax();
tl.add("start") // use a label to start tweens at the same time
tl.to("#path1", 3,  {drawSVG:true}, "start"); // draw path 1
tl.to("#target", 3, { bezier:{values:motionPath1, type:"cubic"}}, "start"); // follow path 1
tl.to("#target", 2, {x:100, y:500}); // move to path 2 starting point 
tl.add("label"); // use a label to start tweens at the same time
tl.to("#path2", 3,  {drawSVG:true}, "label"); // draw path 2
tl.to("#target", 3, { bezier:{values:motionPath2, type:"cubic"} }, "label"); //follow path 2
tl.to("#target", 2, {x:500, y:800}); // move to path 3 if you have more
// lather, rinse, repeat

最后还可以调整下动画细节,比如运动的速度以及路径填充的颜色等等。看起来好像要写很多的代码一样,但是,当你理解了它的原理,其实写起来还是非常的轻松简单,特别是它提供的时间轴(timeline)管理的功能非常方便对动画序列进行管理。最后来看看最后的动画效果:

总结

使用上面介绍的这种手写动画效果的技术还可以用在很多的场景,比如绘制一双鞋子或者是绘制一张框架图等等,充分发挥你的想象力,来创作更多有趣好玩的效果。

更多的关于GreenSock的使用方法可以去官网论坛看看,里面有很多有用的知识,特被是论坛值得经常去逛逛。

可以在Twitter或者论坛上看到我最新分享的关于GreenSock信息。

本文主要是从Animated handwriting effect这篇文章整理而来,有删减,有疏漏或者理解不到位的地方,还请多多指教!