用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;
最後進行代碼的整合
以上即是全部的重點思路
,根據這個思路,寫好代碼,就能夠作出粒子動畫了!