ArrowFlow.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import * as THREE from 'three';
  2. import gasp from 'gsap';
  3. /**
  4. * 箭头流工具类,用于创建箭头流动的相关材质、几何、动画并管理其生命周期
  5. */
  6. export default class ArrowFlow extends THREE.MeshBasicMaterial {
  7. /** 箭头流材质 */
  8. texture: THREE.Texture;
  9. /** 重复次数 */
  10. repeat: THREE.Vector2;
  11. /** 图形偏移量 */
  12. offset: THREE.Vector2;
  13. /** 动画控制器 */
  14. tween: gsap.core.Tween | null = null;
  15. constructor(
  16. texturePath: '/model/img/blueArrow.png' | '/model/img/greenArrow.png' | '/model/img/redArrow.png',
  17. {
  18. repeatX = 20,
  19. repeatY = 4,
  20. /** 0-1 */
  21. offsetX = 0,
  22. /** 0-1 */
  23. offsetY = 1,
  24. } = {}
  25. ) {
  26. const t = new THREE.TextureLoader().load(texturePath);
  27. t.wrapS = THREE.RepeatWrapping;
  28. t.wrapT = THREE.RepeatWrapping;
  29. t.repeat = new THREE.Vector2(repeatX, repeatY);
  30. t.offset = new THREE.Vector2(offsetX, offsetY);
  31. super({ map: t, transparent: true });
  32. this.texture = t;
  33. this.repeat = t.repeat;
  34. this.offset = t.offset;
  35. this.texture.matrix.scale(0.3, 0.3);
  36. this.depthTest = true;
  37. this.depthWrite = true;
  38. this.visible = false;
  39. }
  40. /**
  41. * 启动动画效果
  42. * @param speed number 类型,配合 offset 使用,越小速度越慢,大于 0
  43. * @param offsetX
  44. * @param offsetY
  45. */
  46. startAnimation(speed: number = 1, offsetX: number = -0.01, offsetY: number = 0) {
  47. this.visible = true;
  48. if (this.tween) {
  49. this.tween.kill();
  50. }
  51. this.tween = gasp.to(this, {
  52. duration: 1,
  53. repeat: -1,
  54. onUpdate: () => {
  55. this.texture.offset.setX(this.texture.offset.x + offsetX * speed);
  56. this.texture.offset.setY(this.texture.offset.y + offsetY * speed);
  57. },
  58. });
  59. }
  60. pauseAnimation() {
  61. if (!this.tween) return;
  62. this.tween.pause();
  63. }
  64. resumeAnimation() {
  65. if (!this.tween) return;
  66. this.tween.resume();
  67. }
  68. stopAnimation() {
  69. if (!this.tween) return;
  70. this.tween.kill();
  71. }
  72. hideElement() {
  73. this.visible = false;
  74. if (!this.tween) return;
  75. this.pauseAnimation();
  76. }
  77. showElement() {
  78. this.visible = true;
  79. if (!this.tween) return;
  80. this.resumeAnimation();
  81. }
  82. }