如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报

栏目: CSS · 发布时间: 7年前

内容简介:因为平时也关注网易UEDC的订阅号,前几天就看到了这么一个动效,主题是《网易云音乐2018年度听歌报告》,内容是一个人在努力蹬车因为构图简单,创意又不错,所以就试了下用SVG+CSS动画实现起来的难度,大概费时两个小时左右,效率还是蛮高的,总比用AE实现起来快的多得多,下面就捋一捋实现的过程。画图这种事情,怎么能难得到一个美工呢。在Ai中完成,不考虑太多细节(原效果中有渐变和噪点,这里就省略了,用纯色填充来代替,毕竟人家是一个team,而我是一个人在摸索着战斗)。图做完之后,就要进行拆解了,需要把四个部分拆

因为平时也关注网易UEDC的订阅号,前几天就看到了这么一个动效,主题是《网易云音乐2018年度听歌报告》,内容是一个人在努力蹬车因为构图简单,创意又不错,所以就试了下用SVG+CSS动画实现起来的难度,大概费时两个小时左右,效率还是蛮高的,总比用AE实现起来快的多得多,下面就捋一捋实现的过程。

1. 第一步 先构图,费时1小时

画图这种事情,怎么能难得到一个美工呢。在Ai中完成,不考虑太多细节(原效果中有渐变和噪点,这里就省略了,用纯色填充来代替,毕竟人家是一个team,而我是一个人在摸索着战斗)。

如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报

图做完之后,就要进行拆解了,需要把四个部分拆出来,这四个部分就是要做动效的部分,左大腿,左小腿,右大腿,右小腿。

如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报
如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报

这四个部分为了方便下面做动效,每一个都是要放到单独的图层中的,至于其他图层顺序,就不是那么重要了。

2.第二步 给腿部增加旋转动效,费时0.5小时

做这种涉及到关节类的实现效果,其实是个通路,因为简而言之都是旋转动画,不过是增加了连动,也就是说大腿围绕关节处(即原点)的旋转时要带动小腿围绕大腿末端(小腿动画对应的原点)的旋转。因为有做舞动的机器人的基础,这里就简单了很多,不过仍然做了一点点小的优化,没有像做机器人时拆分成很多SVG,而是直接进行了嵌套。

首先,最最重要的一点,要获取下面图中这三个坐标值。这是做旋转动画时不可或缺的 tranform-origin 值。

大腿的旋转是非常简单的旋转动画设置了,以左腿为例,通过对比左右腿,差不多得到的数据就是大概顺时针旋转了60度,只要在CSS中定义动画参数如下:

/*大腿旋转运动的动画规则*/
@keyframes legLMove{
0% {transform: rotate(0deg)}
100% {transform: rotate(-60deg)}
}
#legL{
animation: legLMove 1s  infinite  alternate;
transform-origin:455px 235px; /*大腿旋转运动的原点*/
}
复制代码
如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报

这样就轻松的得到了大腿运动的动效。

相比之下,小腿就要复杂的多,步步拆解嘛,动画设置的思路也是解题思路,所以,先解决的第一个问题,就是小腿跟随大腿运动的问题。因为在导出SVG之前,在Ai中已经把需要增加动效的部分放置再来不同的图层里,因此,简化的腿部对应的DOM结构是下面这种

<!--左大腿-->
<g id="legL">
	<path d="M……z"/>
</g>
<!--左小腿-->
<g id="calfL">
    <path d="M……z"/>
</g>
复制代码

既然要跟随大腿运动,那好办,直接把左小腿整体部分放到大腿所在的组合 <g> 标签中,就能保证相同的运动了。修改后的DOM结构就变成了:

<!--左大腿-->
<g id="legL">
	<path d="M……z"/>
	<!--左小腿-->
	<g id="calfL">
    	<path d="M……z"/>
	</g>
</g>
复制代码
如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报

现在,这一步已经解决了,那么来解决下一个问题吧,如何让小腿自由的摆动。这里,为了确定小腿的旋转参数,我画了一张示意图。

如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报

这张图中,绿色的弧线就是大腿的运动轨迹,红色的弧线是小腿的运动轨迹,最终小腿部分和大腿部分几乎是平直状态,因为小腿目前是跟随大腿运动的,换句话说,它们两个处于同一个参考系中,因此,在确定小腿的摆动幅度时,不用考虑大腿的状态。(半透明的小腿部分就是最终小腿的状态)。目测,逆时针旋转,100度左右(不用那么精确)。因此,小腿部分的动画规则就出来了:

@keyframes calfLMove{
0% {transform: rotate(0deg)}
100% {transform: rotate(100deg)}
}
#calfL{
animation: calfLMove 1s  infinite alternate;
/*小腿对应的旋转原点 也就是大腿的末端*/
transform-origin:343px 220px; 
}
复制代码

这样,小腿在跟随大腿进行旋转运动的同时实现了自己的旋转动效。(这里实现的这种方法要比之前在做舞动的机械人时优化了很多)。

如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报

左腿完成了,右腿就水到渠成了,不过是一个逆向而已。记得修改DOM结构。

如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报
当然,这个蹬自行车的效果实现的并不好,看上去更像是踩踏板,有时间的话准备开一篇新的文章通过定义 offset-rotate:var(--degMove); 这种在CSS中设置随路径曲率的旋转方向为变量的方法,然后javascript设置定时器改变这个值来实现(这个方法已经测试过了,js同样也可以通过 document.documentElement.style.setProperty

的方法来改变SVG的CSS样式)。此为后话。

3. 第三步 增加音符的动效,费时0.5小时

为了尽可能的和原效果保持一致,这里把音符的动效一并加上了。为了方便查看,我先把无关元素暂时隐藏掉,只保留音符,大概的效果是下面这种:

如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报
音符逐渐变大并沿路径移动后淡化消失的过程。从这句话中,我们提炼出三个元素: 沿路径移动 | 变大 | 变淡

,也就是说对应三种动效设置。 第一步,为了实现路径动画,我先绘制了路径,并确保每个音符落在路径上。

如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报

路径动画的CSS参数写一写:

@keyframes notePath{
0% {offset-distance:0%;}
100% {offset-distance:100%;}
}
#notePath{
offset-path:path('  '); /*绘制的路径path对应的d属性*/
animation:notePath 2s ease infinite;
}
复制代码

音符先不做缩放的处理,以中间状态的为基准,调用这个动画属性后,就可以得到沿路径运动的音符了**(再次强调,在路径动画中,一定要把元素放到画布零位置后再导出。)**:

如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报
继续,下面叠加尺寸变化,animation属性不需要做任何修改,但动画规则中要增加关于缩放,也就是 transform:scale()的定义

。

@keyframes notePath{
0% {
offset-distance:0%;
transform:scale(0.2); /*增加关于缩放的定义,起点缩小至原尺寸0.2*/
}
100% {
offset-distance:100%;
transform:scale(1.5); /*增加关于缩放的定义,终点放大至原尺寸1.5倍*/
}
}
复制代码

此时,音符在沿路径移动的基础上已经叠加了缩放的效果:

如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报

只差最后一步,就是透明度的变化了。通过分析动效,音符并不是在整个动画的时间过程中遵循透明度的变小的规律,而是在变化的中途开始逐渐变淡。这里的处理有两个思路,正好都说一下。第一种,直接定义在统一的动画规则中。既然是中途的变化,那我们CSS可以改成下面这种:

@keyframes notePath{
0% {
offset-distance:0%;
transform:scale(0.2);
}
50%{opacity: 1} /*在中途增加一个关于透明度的定义*/
100% {
offset-distance:100%;
transform:scale(1.5);
opacity: 0.1
}
}
复制代码
如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报

来个好玩的吧, 试试骗过浏览器。 其实浏览器是很傻的,它只会乖乖的看着你的动画规则进行解析,比如透明度这种问题,我们知道 opacity:1 就是完全不透明的了,但浏览器对于opacity定义大于1时,也会按照完全不透明来解析。想到了什么没?

也就是说,我们完全不用增加一个50%的关键帧,而是写成下面这种:

@keyframes notePath{
0% {
offset-distance:0%;
transform:scale(0.2);
opacity: 2; /*透明度设置>1*/
}
100% {
offset-distance:100%;
transform:scale(1.5);
opacity: 0.1;
}
}
复制代码

对浏览器来说,它要执行的过程中,透明度opacity是这样来的,整个时间段,2→0.1,所以差不多前半段是2→1(对应透明度不发生变化),后半段1→0.1(对于透明度变小),也就满足了我们的设定。 第二种方法,虽然略显麻烦,却是很重要的一种方法。在上面的设置中,有一个问题,就是因为animation属性是一个统一定义,这里面包含的参数非常多,比如说速率,也就是我定义为ease值的参数。如果我想让透明度线性速率变化,怎么办呢?来试试 给动画属性叠加多个规则

/*增加一个设置透明度变化的动画规则*/
@keyframes noteOpacity{
	50%{opacity:1}
	100%{opacity:0.1}
}
复制代码

这时,我们要把这个透明度变化的动画规则追加到animation的定义中,追加的方式很简单,逗号后面增加上新的动画规则的属性就可以了:

animation:notePath 2s ease infinite ,noteOpacity 2s linear infinite;
/*新的动画规则noteOpacity可以自由定义其他动画属性*/
复制代码

这种叠加多个动画规则(当然了,你得有个前提,这些动画规则分别定义了不同的属性变化)在一些场景下非常有用的。以这个来做一个非常简单的尝试。当我把noteOpacity这个动画规则的动画时间由2s改成0.5s,为了看出差别,路径动画的时间延迟到了5s,猜猜动效会发生什么变化?

如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报

正如图中所示,这是两个不同的动画规则的叠加效果,因此整个路径运动的过程中会有数次透明度的变化。 好了,让律动的音符和我们骑自行车的动效进行合成吧!

如何借助SVG+CSS用2个小时撸完一个网易云音乐的动效海报

粗制滥造的仿作到此为止。来个小结吧,这篇文章中两个重要的部分:

  1. 对于连动效果,先把整体部分放入需要连动的元素的同级中,以便保持相同的动画设置,再另行设置单独的动画属性。
  2. 给动画属性animation增加多个不同的动画规则的方法非常非常有用。

我也是在做CSS动画的过程中,不断来优化原来总结的知识体系,以后遇到好玩有趣的案例都会做一做。至于CSS变量这个,虽然是2年前的功能,对我来说,却是新的知识点,也准备试一下和js结合之后能怎么玩起来,毕竟要比通过innerHTML方法向CSS文件中添加 <style> 标签和内容要简单明朗的多。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。

Game Programming Patterns

Game Programming Patterns

Robert Nystrom / Genever Benning / 2014-11-2 / USD 39.95

The biggest challenge facing many game programmers is completing their game. Most game projects fizzle out, overwhelmed by the complexity of their own code. Game Programming Patterns tackles that exac......一起来看看 《Game Programming Patterns》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具