import * as THREE from 'three'; import gasp from 'gsap'; /** * 箭头流工具类,用于创建箭头流动的相关材质、几何、动画并管理其生命周期 */ export default class ArrowFlow extends THREE.MeshBasicMaterial { /** 箭头流材质 */ texture: THREE.Texture; /** 流线起点 */ origin: THREE.Vector3; /** 流线终点 */ destiny: THREE.Vector3; /** 流线 */ path: THREE.LineCurve3; /** 重复次数 */ repeat: THREE.Vector2; /** 图形偏移量 */ offset: THREE.Vector2; /** 动画控制器 */ tween: gsap.core.Tween | null = null; constructor( texturePath: '/model/img/blueArrow.png' | '/model/img/greenArrow.png' | '/model/img/redArrow.png', origin: THREE.Vector3, destiny: THREE.Vector3, { repeatX = 20, repeatY = 1, /** 0-1 */ offsetX = 0, /** 0-1 */ offsetY = 0.5, } = {} ) { const t = new THREE.TextureLoader().load(texturePath); t.wrapS = THREE.RepeatWrapping; t.wrapT = THREE.RepeatWrapping; t.repeat = new THREE.Vector2(repeatX, repeatY); t.offset = new THREE.Vector2(offsetX, offsetY); super({ map: t, transparent: true }); this.path = new THREE.LineCurve3(origin, destiny); this.texture = t; this.origin = origin; this.destiny = destiny; this.repeat = t.repeat; this.offset = t.offset; } /** * 启动动画效果 * @param speed number 类型,配合 offset 使用,越小速度越慢,大于 0 * @param offsetX * @param offsetY */ startAnimation(speed: number = 1, offsetX: number = -0.01, offsetY: number = 0) { if (this.tween) { this.tween.kill(); } this.tween = gasp.to(this, { duration: 1, repeat: -1, onUpdate: () => { this.texture.offset.setX(this.texture.offset.x + offsetX * speed); this.texture.offset.setY(this.texture.offset.y + offsetY * speed); }, }); } pauseAnimation() { if (!this.tween) return; this.tween.pause(); } stopAnimation() { if (!this.tween) return; this.tween.kill(); } }