用Three.js作了个字体的粒子系统动画,可设置speedX=speedY=speedZ=1000
的参数改变更画效果,截图以下:javascript
预览地址:https://joeoeoe.github.io/Jon...
此文重讲思路
,为方便解释,部分代码有作修改,此外由于部分代码太长,因此作的是截取,完整代码请看github
gitHub地址:https://github.com/Joeoeoe/Jo...
(有兴趣的同窗能够本身试试调参数尝试出不一样的动画
,滑稽脸.jpg)html
Three的三大基本组件:相机,渲染器,场景在这就不必说了吧,百度有不少资料
接下来咱们分几个步骤来说解如何作出这个粒子动画java
1.思路叙述
2.建立文字几何体并获取点集
3.用HTML5画布编写发光粒子贴图
4.建立粒子系统
5.如何完成粒子动画
6.结束git
1.建立文字几何体,获取点的集合,做为粒子动画的终点
(因此文字几何体不用送入场景中!咱们只是要个位置而已
)
2.选取一个起始点,建立粒子系统(粒子贴图也包含在这部分)
3.编写粒子动画,使粒子系统动起来github
先看函数架构json
let fontLoader = new THREE.FontLoader(); fontLoader.loag('字体包路径',onLoad函数,onProgress函数,onError函数)
这里注意字体包
的选择,不一样字体包的几何体Verctor的数量是不同的,这里我选择optimer_bold.typeface.json
的字体包,你们能够在three.js的集合包中找到各类各样的字体包
待字体包加载完后,咱们便调用onLoad函数,建立字体(先截取onLoad函数的一部分,余下的主要代码均写在onLoad函数中)
canvas
fontLoader.load('../../../package/font/optimer_bold.typeface.json', function (font) { let fontOptions ={ font:font, size:1000, height:20, fontWeight:'bold', curveSegments: 12, //number of points on the curves bevelEnabled:true, bevelThickness:2, bevelSize:8, bevelSegments:5 }; geometry = new THREE.TextGeometry("Jonithan" ,fontOptions); geo_ver = getGeoVer(geometry); .....
注意在onLoad函数中传入参数font
,而后配置字体样式fontOptions
,接着生成字体几何体geometry
,而后就获取点集
这样咱们就得到了终点位置api
首先创造canvas,而且调用createRadialGradient
方法,用于绘制渐变色,绘制渐变色的原理是设定好一组同心圆,用addColorStop方法在不一样位置设定颜色
,以下代码所示架构
function createLightMateria() { let canvasDom = document.createElement('canvas'); canvasDom.width = 16; canvasDom.height = 16; let ctx = canvasDom.getContext('2d'); //根据参数肯定两个圆的坐标,绘制放射性渐变的方法,一个圆在里面,一个圆在外面 let gradient = ctx.createRadialGradient( canvasDom.width/2, canvasDom.height/2, 0, canvasDom.width/2, canvasDom.height/2, canvasDom.width/2); gradient.addColorStop(0,'rgba(255,255,255,1)'); gradient.addColorStop(0.005,'rgba(139,69,19,1)'); gradient.addColorStop(0.4,'rgba(139,69,19,1)'); gradient.addColorStop(1,'rgba(0,0,0,1)');
颜色绘制好后咱们把颜色配置给ctx,并绘制贴图
,等会用于与粒子map
代码以下dom
//设置ctx为渐变色 ctx.fillStyle = gradient; //绘图 ctx.fillRect(0,0,canvasDom.width,canvasDom.height); //贴图使用 let texture = new THREE.Texture(canvasDom); texture.needsUpdate = true;//使用贴图时进行更新 return texture; }
这样,咱们等会就直接拿return的texture做为贴图
接下来咱们就能够创造粒子系统了,先说一下咱们要用到的三个api new Three.Geometry()
new Three.PointsMaterial()
new Three.Points()
思路:建立一个原点Geometry,遍历向Geometry.vertices推入起始点
,再调用new Three.Points()
传入Geometry和粒子配置
生成粒子系统
首先作好粒子配置:
pointsMaterial = new THREE.PointsMaterial({ color:0xffffff, size:80, transparent:true,//使材质透明 blending:THREE.AdditiveBlending, depthTest:false,//深度测试关闭,不消去场景的不可见面 map:createLightMateria()//刚刚建立的粒子贴图就在这里用上 })
接着建立Geomotry和粒子系统
let[x,y,z] =[0,0,0]; let originGeo = new THREE.Geometry(); for (let i = 0; i <originParticleNum; i++){//循环建立Geo originGeo.vertices.push(new THREE.Vector3(x,y,z)); } let originParticleField = new THREE.Points(originGeo,pointsMaterial); return originParticleField;
这样子就得到原点粒子系统了
先看看Three.js中的动画是如何完成的
function animate() { threeConf.stats.begin(); threeConf.renderer.clear(); threeConf.renderer.render(threeConf.scene,threeConf.camera); threeConf.control.update(); particleAnimate();//粒子动画函数 threeConf.stats.end(); requestAnimationFrame(animate); }
即经过不停地调用animate函数,进行渲染
,这个animate函数中的particleAnimate()函数
就是咱们的粒子动画,particleAnimate函数中就改变点的位置
接下来咱们就来编写particleAnimate函数,先贴完整代码再讲过程
function particleAnimate () { for(let i = 0; i < pointsNum; i++){ let originP = originVer[i], destiP = destiVer[i]; let distance = Math.abs(originP.x - destiP.x) + Math.abs(originP.y - destiP.y) + Math.abs(originP.z - destiP.z); if (distance > 1){ //利用距离与坐标差的余弦值 originP.x += ((destiP.x - originP.x)/distance) * speedX * (1 - Math.random()); originP.y += ((destiP.y - originP.y)/distance) * speedY * (1 - Math.random()); originP.z += ((destiP.z - originP.z)/distance) * speedZ * (1 - Math.random()); } } originParticlae.geometry.verticesNeedUpdate=true; }
先搞清楚给部分变量:
pointsNum:粒子数,
originVer:起始点集合,
destiVer:目标位置点集合(就是来自于TextGeometry),
speedX,speedY,speedZ分别表示点在各轴上每次移动的速度
originParticlae:起始点粒子系统
接下来说过程:
大体距离
let distance = Math.abs(originP.x - destiP.x) + Math.abs(originP.y - destiP.y) + Math.abs(originP.z - destiP.z);
余弦值
进行距离的自增运算if (distance > 1){ //利用距离与坐标差的余弦值 originP.x += ((destiP.x - originP.x)/distance) * speedX * (1 - Math.random()); originP.y += ((destiP.y - originP.y)/distance) * speedY * (1 - Math.random()); originP.z += ((destiP.z - originP.z)/distance) * speedZ * (1 - Math.random()); }
originParticlae.geometry.verticesNeedUpdate=true;
最后进行代码的整合
以上即是全部的重点思路
,根据这个思路,写好代码,就能够作出粒子动画了!