当初由于喜欢做动效所以才开始学Threejs,但是学了Threejs后又很少用它做动效,大多数都是发的一些比较偏理论的文章,主要原因除了我比较菜之外,还是因为要做个酷炫的Threejs动效难度还是比较大的,要掌握的知识维度比较大,但是前几天不知道具体哪一天,我忽然觉得我这么想其实也有问题,问题在于再复杂的东西,也都是由简单的东西凑在一起,只要抽丝剥茧一番对它多分析一下,我感觉,用咱现掌握的知识,也并不是做不出好看的动效,不信我们接下来试试看
动效来源于生活
一般做动效都会像画画一样,先找个事物然后对着它画,动效也一样,没有个目标,心里没有个模板,自己都不知道应该从哪些方面调动效,所以第一步先确定要做啥,前阵子看了部电影叫《龙卷风》,里面那些人都喜欢正面硬刚龙卷风,那么这次动效我们也来尝试做个龙卷风
思路
前面说了做动效前先分析一下,不可能一下子上来就做个龙卷风,咱是程序员又不是魔术师,先来张图片看看龙卷风长啥样
再问下AI给一个对于龙卷风的定义是啥
从给的定义中我们获取到了如下信息
- 剧烈旋转:咱这个动效要转起来
- 涡旋:要有螺旋一样的形状
- 从雷暴云向下:方向得是由上向下
- 像漏斗:要像漏斗~
- 携带碎片:几何体必须得是粒子
这么一分析是不是感觉好像并不是很难,不是做不出来,不管咋样,先把能做的先做出来
创建粒子
再怎么菜这第一步肯定会,没啥难度,使用最不耗性能的BufferGeometry
来创建粒子
这里创建了1500个粒子,暂时位置给他随机设置,同时也设置了颜色属性,方便后面给动效调色,最后分别将位置samplePosition
和colors
设置给position
与color
属性,就得到了如下一堆粒子
构建漏斗形状
可能没法一下子做出一个漏斗,那么不妨先做个跟漏斗比较相似的形状,也就是圆柱体,要让这些粒子组成圆柱体形状,那么粒子的位置摆放起来就要有规律了,这个规律也就是一个圆柱体上的任意高度上的点都是在一个圆周上的,于是就需要定义两个变量,圆柱体的高以及半径
然后要做的就是计算在任意高度的一个圆周上的点坐标,这里将会用到正余弦函数
高度和角度都是取的随机值,最后再通过正余弦函数得到x与z轴的坐标,一个圆柱体就做好了
接下来就是要将圆柱体变成一个漏斗,其实漏斗就是一个半径从上到下逐渐减小的圆柱体,解释有点牵强但是不难帮助理解,在上述计算的代码中,x,z坐标的计算方式不变,但是乘上的半径不能是一个定值,要通过当前高度计算出来,计算公式如下
任意高度半径 = 最大半径*任意高度/总高度
这个公式如何得到的呢?可以看下下面的这张草图
这里就要用到初中时候的几何知识了,相似三角形对应边成比例,图中的两个相似三角形我们已知高以及最大三角形的底边,那么就能通过比例计算出较小三角形的底边,上述公式就是这么来的,下面用代码实现
就多加了一行半径的计算,我们就能将圆柱体改为漏斗状,效果如下
螺旋状
使粒子组成一个漏斗形状是第一步,接下来就是要让所有粒子都整齐的排列起来并形成螺旋状,螺旋其实就是在高不断增大的时候不停的在画圆,也就是每一个粒子所在的高度都要比前一个低一些,所以先将高度等分,等分的数量也就是粒子的数量
除了高需要等分之外,粒子所在圆周上的角度也需要逐个变大,那么逐个变多大呢?需要先算出粒子之间的角度差值
暂定为1度,然后我们总共有num
个粒子,那么每个粒子所在的角度这里用一个数组保存起来
同时增加了访问angleList
的下标angleIndex
,每次计算完一个粒子的坐标,angleIndex
就自增1,然后就获取下一个粒子需要的角度,代码如下
此时得到了如下这样的螺旋状粒子图
我们的粒子是螺旋起来了,但是跟龙卷风那样的螺旋还不太一样,都知道龙卷风有很多个螺旋,所以这里还需要增加螺旋数量,如何增加呢?我们不妨先想一想现在为什么只有这么几个螺旋,不就是因为每个粒子只走1度,总共1500个粒子,也就是粒子总共也就经过了1500度,那么1500度不就是五圈不到一点吗,现在就知道如何增加螺旋数量了,增加粒子经过的圆周角度就好了,之前每个粒子之间的角度差只有1度,那么这里将它增大到5度
此时的螺旋数量就变多了
转动螺旋漏斗
之前定下的目标还有一个没完成,那就是让漏斗转起来,整个转动分两个部分,一个是所有粒子绕着中心转动,另一个是每个粒子单独晃动,先来实现简单的,绕着中心转,也就是绕着y轴转,这里创建一个刷新函数,并且在函数内部给sphereparticleSystem
的y轴旋转值自增0.02
接着是让粒子在整体绕着中心旋转的时候,自己也可以晃动,毕竟我们无论从网上还是电影里,看到的龙卷风都不会是笔挺的站在那边吹,反而都长的比较歪七扭八,东倒西歪,要实现这个效果就要让每个粒子水平方向的坐标,也就是x轴或者z轴的坐标有个周期性的波动过程,我们也称之为正弦或者余弦运动,以在z轴上做正弦运动为例
由于正弦运动是随着时间变化的运动,所以变量time
表示当前时间,单位是秒,随着时间变化,给每个粒子增加一个相位偏移的值,也就是Math.sin(time*i*0.01)
,最终我们要的龙卷风粒子动效就完成了
总结
我们开头所说的那些龙卷风特性,比如漏斗,螺旋,旋转等都已经实现了,要说整个动效的制作过程中最难的地方是什么,那肯定都是些数学知识,我们用到了相似三角形,正余弦函数,圆周运动来做这个动效,所以要做好动效,不得不去恶补一些以前学到的数学知识,不过也可以借助AI来帮助你回忆起那些数学公式,好了,希望这个龙卷风能给你在这个炎炎夏日带来丝丝凉爽,拜拜~