| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- import * as THREE from 'three';
- class Fly {
- points;
- length;
- circle;
- opacity;
- size;
- progress;
- frameId;
- geometry;
- material;
- texture;
- obj;
- color;
- constructor(points, length, circle = 2, color = '#ff00ff', opacity = 1, size = 10) {
- this.points = points; // 路径
- this.length = length; // 长度(粒子数)
- this.circle = circle; // 周期
- this.color = color; // 颜色
- this.opacity = opacity; // 透明度
- this.size = size; // 大小
- this.progress = 0;
- this.frameId = null;
- this.geometry = null;
- this.material = null;
- this.texture = null;
- this.obj = null;
- this.createFly();
- }
- createFly() {
- // 几何体
- this.geometry = new THREE.BufferGeometry();
- this.updateFly();
- // 纹理和材质
- this.texture = new THREE.TextureLoader().load('/model/img/spark.png');
- this.material = new THREE.PointsMaterial({
- color: this.color,
- map: this.texture,
- // alphaTest: 0.9,
- transparent: true,
- depthWrite: false,
- // depthTest: false,
- opacity: this.opacity,
- //blending: THREE.AdditiveBlending,
- size: this.size,
- sizeAttenuation: true,
- side: THREE.DoubleSide,
- });
- // 修正着色器
- this.material.onBeforeCompile = (shader) => {
- const vertex = `
- attribute float aScale;
- void main() {
- `;
- const vertex1 = `gl_PointSize = size * aScale;`;
- shader.vertexShader = shader.vertexShader.replace('void main() {', vertex);
- shader.vertexShader = shader.vertexShader.replace('gl_PointSize = size;', vertex1);
- };
- // 物体
- this.obj = new THREE.Points(this.geometry, this.material);
- }
- // 更新
- updateFly() {
- // 计算新数据
- const posArr = [];
- const scaleArr = [];
- const posIndex = Math.floor(this.progress * this.points.length);
- const flyPointArr = this.points.filter((point, index) => {
- if (index >= posIndex && index <= posIndex + this.length) return true;
- });
- flyPointArr.forEach((point, index) => {
- posArr.push(...point);
- // scaleArr.push((index + 1) / this.length);
- const scale = Math.random() * 1;
- scaleArr.push(scale);
- });
- // 更新几何体
- this.geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(posArr), 3));
- this.geometry.setAttribute('aScale', new THREE.BufferAttribute(new Float32Array(scaleArr), 1));
- this.geometry.boundingBox = new THREE.Box3(new THREE.Vector3(10000, -10000, 10000), new THREE.Vector3(-10000, 10000, -10000));
- this.geometry.boundingSphere = new THREE.Sphere(new THREE.Vector3(0, 0, 0), 10000);
- }
- // 移动
- move() {
- if (this.frameId) return;
- const clock = new THREE.Clock(); // 时钟
- const h = () => {
- this.frameId = requestAnimationFrame(h);
- const dt = clock.getDelta();
- this.progress += dt / this.circle; // 更新进度
- if (this.progress > 1) this.progress = 1;
- this.updateFly();
- if (this.progress == 1) this.progress = 0;
- };
- this.frameId = requestAnimationFrame(h);
- }
- // 停止
- stop() {
- if (this.frameId) {
- cancelAnimationFrame(this.frameId);
- this.frameId = null;
- }
- }
- clear() {
- this.points = [];
- }
- }
- export default Fly;
|