ThreeJS 粒子系统中,THREE.Points是用来创建点的类,也用来批量管理粒子,基于几何体的顶点来渲染每个粒子。这个类的构造函数有两个参数,geometry(几何体)和material(材质),几何体参数用来设置粒子的位置坐标,而材质参数用来设置粒子的外观。下面利用ThreeJS的粒子系统来实现雪花飘落动画。
1. 寻找素材
1) 背景图片
选择一张雪景图片作为背景图
2) 雪花图片
为了让动画效果更好,使用两种不同形状的雪花实现雪花飘落效果。
2. HTML部分
网页中添加canvas画布所在的元素
<div id="snowBackground"></div>
3. JS部分
1) 初始化渲染器、场景、摄像机
var width = 550; // 画布的宽度
var height = 366; // 画布的高度
// 渲染器
var renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(width, height);
// 将canvas添加到指定元素
var element = document.getElementById('snowBackground');
element.appendChild(renderer.domElement);
// 场景
var scene = new THREE.Scene();
// 正交投影摄像机
var camera = new THREE.PerspectiveCamera(45, width/height, 2, 500);
camera.position.set(0, 0, 40); // 摄像机位置
// 照相机默认沿z轴负方向观察,通过设置lookAt的位置可以改变观察的方向
camera.lookAt(new THREE.Vector3(0, 0, 0));
scene.add(camera);
2) 利用平面几何体添加背景
// 平面几何体
var planeGeometry = new THREE.PlaneBufferGeometry( width, height);
planeGeometry.translate(0, 0, -400); // 平面几何体位置
// 背景纹理
var planeTexture = new THREE.TextureLoader().load('./snow_bg.jpg');
// 背景材料
var planeMaterial = new THREE.MeshBasicMaterial({
map: planeTexture
});
// 背景网格
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
// 将背景添加到场景
scene.add(plane);
3) 利用THREE.Points增加雪花粒子
由于使用了两种雪花形状,每一个形状需要创建一个THREE.Points对象
var typeNum = 2; // 雪花种类
var range = 50; // 雪花出现范围
// 雪花纹理
var texture = new THREE.TextureLoader().load('./snowflake.png');
// 使用图片纹理材质
var materials = [];
for (var i = 0; i < typeNum; i++) {
var material = new THREE.PointsMaterial({
size: 2,
map: texture, // 纹理
transparent: true, // 透明
opacity: 1, // 透明度
depthTest: false, // 可以去掉texture的黑色背景
blending: THREE.AdditiveBlending // 融合模式
});
material.map.offset = new THREE.Vector2(1/typeNum * i, 0);
material.map.repeat = new THREE.Vector2(1/typeNum, 1);
materials.push(material);
}
// 通过自定义几何体设置粒子位置
var geoms = [];
for (var k = 0; k < typeNum; k++) {
var geom = new THREE.Geometry();
for (var i = 0; i < 100; i++) {
// 随机生成雪花的位置
var v = new THREE.Vector3(
Math.random() * range - range/2,
Math.random() * range - range/2,
Math.random() * range - range/2
);
// 随机生成雪花分别沿x、y、z轴方向移动速度
v.velocityY = 0.1 + Math.random() / 5;
v.velocityX = (Math.random() - 0.5) / 3;
v.velocityZ = (Math.random() - 0.5) / 3;
// 添加顶点
geom.vertices.push(v);
}
geoms.push(geom);
}
// 点云
var clouds = [];
for (var i = 0; i < typeNum; i++) {
var points = new THREE.Points(geoms[i], materials[i]);
clouds.push(points)
scene.add(points);
}
4) 利用requestAnimationFrame实现动画
(function animate () {
clouds.forEach(function (points, i) {
var vertices = points.geometry.vertices;
vertices.forEach(function (v, idx) {
// 计算位置
v.y = v.y - (v.velocityY);
v.x = v.x - (v.velocityX);
v.z = v.z - (v.velocityZ);
// 边界检查
if (v.y <= -range/2) v.y = range / 2;
if (v.x <= -range/2 || v.x >= range/2) v.x = v.x * -1;
if (v.z <= -range/2 || v.z >= range/2) v.velocityZ = v.velocityZ * -1;
});
//重要:渲染时需要更新位置(如果没有设为true,则无法显示动画)
points.geometry.verticesNeedUpdate = true;
});
renderer.render(scene, camera);
requestAnimationFrame(animate);
})();
十五年编程经验,今年1月整理了一批2019年最新WEB前端教学视频,不论是零基础想要学习前端还是学完在工作想要提升自己,这些资料都会给你带来帮助,从HTML到各种框架,帮助所有想要学好前端的同学,学习规划、学习路线、学习资料、问题解答。只要加入WEB前端学习交流Q群:296212562,即可免费获取。
网友评论