眼瞅着马上就要过年了,公司里的小伙伴们也都三三两两的回家去了,就我还有几个天选打工人仍旧在搬砖房里面认真工(mo)作(yu),不过也刚好趁着这几天有空余时间,又可以打磨打磨我那蹩脚的Threejs功底,之前写过两篇比较基础入门的文章,算是简单了解了一下Threejs,这次做点小动效吧,简单的先试试手,至于写点啥,要过年了嘛,说到过年,现在真的没以前那么有意思,有盼头了,但唯独有一样,面对它的时候,大家脸上还是能绽放出发自肺腑的笑容的,那就是红包,无论是在各种群里面抢红包,还是小时候走亲戚收到长辈给的红包,我想每个人应该都挺开心的吧,那么今天,我们就做个漫天飞舞的红包吧
创建三要素
场景
相机
相机的位置选在了(0,0,50)主要是因为我们这个动效是正面去看的,没必要去仰望或者俯视它
渲染器并添加至页面中
创建缓冲对象
由于是要做多个红包的效果,第一个想到的就是每个红包作为一个独立的几何体,然后统统塞到一个Object3D
对象里面去,但这也就想想,毕竟这样做太耗费性能,这里需要使用BufferGeometry
缓冲几何体,用它来存储所有红包所对应的顶点数据,上代码
mCount
是顶点的数量,我们这里定义为100个,然后在创建个Float32Array
数组用来存放顶点的坐标,在for
循环体内就是给坐标赋值的过程,分别在x,y,z轴的某个范围内取值,缓冲数据做好了之后,就将pos
设置给缓冲对象BufferGeometry
的position
属性,我们缓冲对象就做好了
创建点对象
缓冲对象做好了之后就要将这些数据转换成能够看得见的粒子效果了,这里就要用到Three.Point
对象,它的构造函数内部接收两个参数,一个就是刚才我们做好的缓冲对象,另一个就是点材质PointsMaterial
这里的点的大小稍微设置的大一些,因为一会还要显示红包纹理,现在暂时用色值来代替,实际效果如下
设置红包纹理
点的样式已经做好了,现在就要将红包纹理设置上去了,我们的红包纹理长这样
先将纹理加载器创建出来
然后去加载我们刚才找到的那张红包纹理图
最后将加载出来的纹理temptexture
设置到点材质的map
属性里面
我们现在就能看到一大堆红包出现在屏幕上了
接下来就要准备让这些红包动起来
安装Tween.js
要让这堆红包动起来,最简单有效的办法就是使用动画库Tween.js,先将库导入到项目中
由于是在TypeScript的项目中,所以还要安装@types/tween.js库,不然tween没法导入到项目中,完事了之后,我们将tween导入进来
创建动画的目标位置
Tween.js上手起来还是蛮简单的,只需要知道动画对象的起始位置坐标以及终止位置坐标,就可以让对象动起来,那么这里的起始位置就是我们粒子缓存起来的顶点位置,获取的方式如下
有了起始位置的坐标位置,那么终止位置的坐标如何设置呢?一个办法就是任意找一个几何对象,将它的顶点坐标取出来作为终止位置的坐标,但是不同几何对象的顶点数量不同,不能跟我们的红包数量一一对应起来,所以我们只能自己去创建终止位置的顶点坐标,这些坐标排列的方式呈矩形方式排列
同样也是生成了一个数组endpos
用来存放终止位置的顶点坐标,然后矩型的长宽的大小就使用mCount
开根号获得,得到的side
就是矩形的边长,再通过长宽的嵌套遍历,得到顶点坐标的x,y值,z就默认为0,代表矩形刚好是贴着x轴的方向
开启动画
每个红包都会有一个动画效果,所以我们要从初始位置的顶点坐标里将每个坐标拿出来分别设置上tween动画
easing
用来设置动画的速率变化规律,这里使用的是正弦缓动Sinusoidal
,InOut
表示动画开始快速,中期减速,后期缓慢,还有其余两个值
In
:起始缓慢,中期加速,后期减速Out
:起始快速,中期减速,后期缓慢
repeat
表示动画重复次数,delay
表示动画延迟多少时间开始,单位是毫秒,onUpdate
是动画在进行中的回调,我们在回调函数中开启实时更新顶点坐标,start
表示开启动画,另外还需要去更新动画,不然就算开启了动画,界面上也不会有任何动画效果
那么一个红包从初始位置到终止位置的动画就做好了
我们发现虽然设置了repeat
次数,但是每次动画完成之后,红包会瞬间回到初始位置,而不是从终止位置在反方向动画到初始位置,要做到这一点还需要再设置一个函数,函数名叫yoyo
,起初我以为这个函数的命名是闹着玩的,后来一翻文档才发现,人家是正儿八经的正式成员,它的默认值是false
,我们将它设置成true
动画就能反方向进行了
现在再做点修改,目前所有动画的运行时间以及延迟时间都是一样的,如果我们将动画的延迟时间以及运行时间按照下标值来计算,会有什么效果呢?试一下
由于红包数量是100个,时间是2000毫秒,所以每一个红包的运行时间以20毫秒来递减,延迟时间以20毫秒来递增,改完后效果变成了这样
整体效果看起来就变得有次序了一点,红包的动画就这些,我们再给整体加个背景,让页面看起来丰富一些
背景纹理
再从网上找个外滩夜景的图片,准备拿这个作为我们场景的背景,图片长这样
同样使用纹理加载器TextureLoader
将这个图片转换成纹理,再将它设置给scene.background
完成以后现在的效果是这样子的
要是天上真的能飘红包,那就泰裤辣~但是现在这动效感觉还是差点啥,尤其是红包收起来那会,整体有点空荡荡的,不喜庆,那就再给它添点东西,比如加点亮片,搞个亮片雨啥的
制作亮片雨
亮片雨说白了原型与我们上面做的红包一样,也是要用Three.Point
对象做出来,所以第一步还是要创建亮片雨的缓冲模型,我们先把顶点数据做出来
然后创建缓冲模型,将上述做出来的顶点数据设置到这个模型的position
属性中去
现在我们界面上已经能看到加载出来的粒子了
虽然有粒子了,但不亮啊,离咱们要的效果还有段距离,那么我们接下来要给这些粒子上点色,由于色值是用rgb格式表示的,所以也要创建一个数组用来存放给顶点染色的rgb数据
每个顶点颜色随机生成,然后同样也是将colorArray
设置到缓存模型的color
属性上
光设置给color
属性还不够,点材质PointMaterial
还需要开启顶点着色功能,不然就算设置了颜色数据也是白忙
现在界面上的粒子就变成彩色的了
在改变下颜色的取值范围,因为我们要的是亮片雨,以金黄色为主,红色也可以保留一点,就相当于我们红包的主体色一样
我们界面上的效果就变成了这样
是不是感觉一下子就到位了,还剩下最后一步,让这些亮片动起来,就跟下雨一样,那么我们只需要在y轴上不断更改亮片的位置就好了,到了临界的地方再让亮片回到最上面,代码如下
大功就告成了,上最终效果图
总结
一个红包动效就做好了,其实原本还想试一下Raycaster
,这样就能实现一下点击某个红包放大的效果,但是忘了我这边用的是一整个Three.Point
,导致放大是放大了,但就是所有红包一起放大,没办法放在下次用别的动效来演示吧,明天就是除夕了,提前祝各位春节快乐~