上节学了各种形状的粒子发射器,但它们还是有些呆板。
比如我希望粒子在运动的过程中逐渐变小,而现在粒子大小是不变的。

比如我希望粒子在运动过程中颜色逐渐变浅,而现在粒子颜色也是不变的。
还有,我希望粒子运动速度是先快后慢,而现在也是控制不了的。
如何控制粒子运动过程中的行为呢?
这就要用 addBehavior 的 api 了。
我们来试试:
npx create-vite three-quarks-behavior-control

进入项目,安装依赖:
npm install
npm install --save three
npm install --save-dev @types/three
改下 src/main.js
import './style.css';
import * as THREE from 'three';
import {
OrbitControls
} from 'three/addons/controls/OrbitControls.js';
import mesh from './mesh.js';
const scene = new THREE.Scene();
scene.add(mesh);
const directionLight = new THREE.DirectionalLight(0xffffff);
directionLight.position.set(500, 600, 800);
scene.add(directionLight);
const ambientLight = new THREE.AmbientLight();
scene.add(ambientLight);
const helper = new THREE.AxesHelper(1000);
scene.add(helper);
const width = window.innerWidth;
const height = window.innerHeight;
const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 10000);
camera.position.set(500, 600, 800);
camera.lookAt(0, 0, 0);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height)
function render() {
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
document.body.append(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
创建 Scene、Light、Camera、Renderer。
改下 style.css
body {
margin: 0;
}
安装下粒子效果库:
npm install --save three.quarks
在 mesh.js 初始化下 three.quarks
import * as THREE from "three";
import { BatchedParticleRenderer, ConstantValue, GridEmitter, IntervalValue, ParticleSystem,PointEmitter,RandomColor, RenderMode } from "three.quarks";
const group = new THREE.Group();
const batchRenderer = new BatchedParticleRenderer();
group.add(batchRenderer);
const loader = new THREE.TextureLoader();
const texture = loader.load('./point.png');
const particles = new ParticleSystem({
duration: 5,
looping: true,
startLife: new IntervalValue(0, 3),
startSpeed: new IntervalValue(0, 600),
startSize: new ConstantValue(100),
startColor: new RandomColor(
new THREE.Vector4(1, 0.5, 0.5, 1),
new THREE.Vector4(0.5, 0.5, 1, 1)
),
emissionOverTime: new ConstantValue(5),
shape: new GridEmitter({
width: 300,
height: 300,
row: 1,
column: 1
}),
material: new THREE.MeshBasicMaterial({
map: texture,
transparent: true,
side: THREE.DoubleSide
})
});
group.add(particles.emitter);
batchRenderer.addSystem(particles);
export {
batchRenderer
}
export default group;
我们主要是看粒子的变化,所以用了 GridEimtter,一行一列。
然后每次发射 5 个粒子,大小是固定的 100
在 main.js 里引入下:
import { batchRenderer } from './mesh.js';
const clock = new THREE.Clock();
function render() {
const delta = clock.getDelta();
renderer.render(scene, camera);
requestAnimationFrame(render);
if(batchRenderer) {
batchRenderer.update(delta);
}
}
render();
跑一下:
npm run dev


可以看到,在整个生命周期中,粒子大小都是不变的。
如何让粒子在生命周期中逐渐变小呢?
使用 addBehavior 来添加行为。

SizeOverLife 是 size 在整个生命周期的变化。
我们定义贝塞尔曲线来变化,四个值分别是 4 个时间点的大小。
particles.addBehavior(
new SizeOverLife(new PiecewiseBezier(
[
[
new Bezier(1, 0.7, 0.3, 0),
0
]
]
))
)

可以看到,现在粒子就会逐渐变小了。
速度也可以变化,现在是匀速:

particles.addBehavior(
new SpeedOverLife(new PiecewiseBezier(
[
[
new Bezier(0.1 ,0.8, 0.3, 10),
0
]
]
))
);
最开始是初始速度的 0.1,先变大,后变小,最后结束的时候加速到 10 倍速度。
看下效果:

可以看到,开始比较慢,最后变的很小的时候就运动特别快了。
如果想让颜色也逐渐变化呢?
那自然就是用 ColorOverBehavior 来控制:

particles.addBehavior(
new ColorOverLife(new ColorRange(
new THREE.Vector4(1, 0, 0, 1),
new THREE.Vector4(0, 0, 1, 1)
))
);
指定颜色变化的范围,从红变为蓝:
现在小球在运动过程中就会变色了。
此外,还可以运动过程中修改 x、y、z:

particles.addBehavior(new ForceOverLife(
new ConstantValue(0),
new ConstantValue(-500),
new ConstantValue(0)
));
这里我们运动过程中 y 逐渐向下。

这样,就可以控制运动过程中的位置变化了。
此外,还可以变换角度,这里用圆看不出来,我们换一个图片:




可以看到,现在心在运动过程中旋转角度是不变的。
这个旋转角度也可以控制:

particles.addBehavior(new RotationOverLife(
new IntervalValue(-Math.PI, Math.PI))
);
设置一个 -Math.PI 到 Math.PI 的随机值。

这样,运动过程中就会做随机的旋转。
案例代码上传了小册仓库
总结
这节我们学了如何自定义粒子运动的生命周期中的行为。
可以通过 addBehavior 添加自定义行为:
- SizeOverLife 控制大小变化
- SpeedOverLife 控制速度变化
- ColorOverLife 控制颜色变化
- ForceOverLife 控制 x、y、z 变化
- RotationOverLife 控制旋转角度
通过自定义各种属性的变化,可以实现更复杂的粒子效果。