threejs粒子效果有两种方法:THREE.Particle和THREE.ParticleSytem,THREE.Sprite。本案例中的粒子系统就是通过Sprite
类来实现的。
初始化基本配置
首先定义基本的用到的,通常包括容器,相机,场景,渲染器,性能监控组件,光线等
/**
* 初始化
*/
function init() {
// 容器
container = document.createElement( 'div' );
document.body.appendChild( container );
// 定义相机
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 3000 );
camera.position.z = 1000;
camera.position.y = 0;
// 定义场景
scene = new THREE.Scene();
// 定义渲染器
renderer = new THREE.CanvasRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
// 定义性能监控组件
stats = new Stats();
container.appendChild( stats.dom );
window.addEventListener( 'resize', onWindowResize, false );
// 定义光线
const ambientLight = new THREE.AmbientLight('#fff', 1) // obj 唯一 id
scene.add(ambientLight)
}
定义粒子
使用Sprite来制作粒子可以实现以下两种需求:
1.使用useScreenCoordinates:true属性建立一个独立于camera摄像范围之外的元素,即它在屏幕上的位置不受camera的位置和焦点变化而变化,它的移动、定位、缩放是基于屏幕坐标的。
2.与在CanvasRenderer渲染器中使用THREE.Particle创建粒子一样,不需要使用THREE.ParticleSytem, 在WebGlRenderer渲染器中使用THREE.Sprite创建的粒子可以直接添加到scene中。三维场景中创建出来的精灵总是面向镜头的。即不会有倾斜变形之类透视变化,只有近大远小的变化。
- Sprite默认大小是1*1,设置Sprite大小需要使用scale进行缩放
- Sprite的样式通过参数meterial定义,参数meterial是使用THREE.SpriteMaterial类创建的材质对象
- THREE.SpriteMaterial可以定义精灵的颜色和纹理,纹理对象可以调用new THREE.ImgesUtils.loadTexture(url)来引用一张图片作为纹理,也可以调用new THREE.CanvasTexture( canvas),使用动态绘制的canvas图作为纹理。
/**
* 初始化粒子
*/
function initParticle() {
//画点
var program = function ( context ) {
context.beginPath();
context.arc( 0, 0, 0.5, 0, PI2, true );
context.fill();
};
// 定义组
group = new THREE.Group();
// 将组合添加到场景中
scene.add( group );
//创建一个球型用作最后的形状
var geometry = new THREE.SphereGeometry( 500, 32, 32 );
// 几何体geometry的顶点位置属性
var vl = geometry.vertices.length;
for ( var i = 0; i < vl; i++ ) {
//为每个点附上材质
var material = new THREE.SpriteCanvasMaterial( {
color: Math.random() * 0x808008 + 0x808080,
program: program
} );
// 用精灵图定义粒子
particle = new THREE.Sprite( material );
particle.position.x = 0;
particle.position.y = -500;
particle.position.z = 0;
particle.scale.x = particle.scale.y = Math.random() * 6 + 3;
var timerandom = 1*Math.random();
//为每个点加缓动动画
// 爆炸
TweenMax.to(
particle.position,
timerandom,
{
x:geometry.vertices[i].x+(0.5-Math.random())*100,y:geometry.vertices[i].y+(0.5- Math.random())*100,z:geometry.vertices[i].z+Math.random()*100,delay:1.8,
}
);
// 爆炸完粒子下落
TweenMax.to(
particle.position,
timerandom,
{
y:'-=1500',z:'300',delay:1.8+timerandom,ease:Power2.easeIn
}
);
group.add( particle );
}
}
定义渲染过程
/**
* 渲染过程
*/
function render() {
delta = 10 * clock.getDelta();
// 速度
var speed = 80;
delta = delta < 2 ? delta : 2;
var dur = new Date().getTime() - t1;
if (dur < 1800) {
var k = 0;
group.traverse(function(child) {
if (child.position.y < 0) {
child.position.y += delta * speed * Math.random();
}
});
}
renderer.render( scene, camera );
}
动画渲染
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}