资讯专栏INFORMATION COLUMN

Three.js 粒子系统动画与发光材质——利用HTML5画布绘制

Wuv1Up / 3467人阅读

摘要:用做了个字体的粒子系统动画,可设置的参数改变动画效果,截图如下预览地址此文重讲思路,为方便解释,部分代码有做修改,此外因为部分代码太长,所以做的是截取,完整代码请看地址有兴趣的同学可以自己试试调参数尝试出不同的动画,滑稽脸的三大基本组件相机

用Three.js做了个字体的粒子系统动画,可设置speedX=speedY=speedZ=1000的参数改变动画效果,截图如下:

预览地址:https://joeoeoe.github.io/Jon...
此文重讲思路,为方便解释,部分代码有做修改,此外因为部分代码太长,所以做的是截取,完整代码请看github
gitHub地址:https://github.com/Joeoeoe/Jo...
(有兴趣的同学可以自己试试调参数尝试出不同的动画,滑稽脸.jpg)

Three的三大基本组件:相机,渲染器,场景在这就没必要说了吧,百度有很多资料
接下来我们分几个步骤来讲解如何做出这个粒子动画

目录:

1.思路叙述
2.创建文字几何体并获取点集
3.用HTML5画布编写发光粒子贴图
4.创建粒子系统
5.如何完成粒子动画
6.结束

一.思路叙述

1.创建文字几何体,获取点的集合,作为粒子动画的终点(所以文字几何体不用送入场景中!我们只是要个位置而已
2.选取一个起始点,创建粒子系统(粒子贴图也包含在这部分)
3.编写粒子动画,使粒子系统动起来

二.创建字体

先看函数架构

let fontLoader = new THREE.FontLoader();
fontLoader.loag("字体包路径",onLoad函数,onProgress函数,onError函数)

这里注意字体包的选择,不同字体包的几何体Verctor的数量是不一样的,这里我选择optimer_bold.typeface.json的字体包,大家可以在three.js的集合包中找到各种各样的字体包
待字体包加载完后,我们便调用onLoad函数,创建字体
(先截取onLoad函数的一部分,余下的主要代码均写在onLoad函数中)

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,然后就获取点集
这样我们就获得了终点位置

三.编写发光粒子贴图

首先创造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
代码如下

//设置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 

这样子就获得原点粒子系统了

五.如何完成粒子动画

先看看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:起始点粒子系统
接下来讲过程:

1.获取起始点与目标点的大致距离
let distance = Math.abs(originP.x - destiP.x) + Math.abs(originP.y - destiP.y) + Math.abs(originP.z - destiP.z);
2.距离大于1时进行移动,这里利用余弦值进行距离的自增运算
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());
        }
3.最后设置更新粒子系统点为true
    originParticlae.geometry.verticesNeedUpdate=true;
六.结束

最后进行代码的整合
以上便是所有的重点思路,根据这个思路,写好代码,就可以做出粒子动画了!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96537.html

相关文章

  • three.js 简介

    摘要:对于自身不能发光的物体,需要给场景添加光源从而达到可视的效果。中渲染阴影的开销比较大,所以默认物体是没有阴影的,需要单独开启。主要用于检测动画运行时的帧数,可以显示表示每秒多少帧和每帧多少毫秒,越大越好,但太大会影响性能,一般为左右。 一、WebGL 与 three.js WebGL(Web Graphics Library)是一种3D绘图协议,它允许把JavaScript和OpenG...

    yankeys 评论0 收藏0
  • 前端特效demo | 值得收藏的6个 HTML5 Canvas 实用案例

    摘要:模拟飞机航班线路动画一款基于的飞机航班线路模拟动画,它模拟了许多航班在不同目的地的起飞降落数量。跳动加载动画可调节参数这是一款基于的跳动加载动画,它的另一个特点是可以动态调节动画参数。 showImg(https://segmentfault.com/img/bVblze6?w=900&h=383); HTML5 动画在Canvas 上得到了充分的发挥,我们 VIP 视频也分享过很多相...

    Chao 评论0 收藏0
  • WebGL three.js学习笔记 使用粒子系统模拟时空隧道(虫洞)

    摘要:学习笔记使用粒子系统模拟时空隧道本例的运行结果如图时空隧道演示地址的粒子系统的粒子系统主要是依靠精灵体来创建的,要实现中的粒子系统创建,一般有两种方式。 WebGL three.js学习笔记 使用粒子系统模拟时空隧道 本例的运行结果如图:showImg(https://img-blog.csdnimg.cn/20190426222855492.png?x-oss-process=ima...

    Guakin_Huang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<