diff --git a/frontend/src/app/particles/components/frames/frames.component.html b/frontend/src/app/particles/components/frames/frames.component.html
index b988a6b..4feebde 100644
--- a/frontend/src/app/particles/components/frames/frames.component.html
+++ b/frontend/src/app/particles/components/frames/frames.component.html
@@ -11,11 +11,16 @@
- Particle {{ i + 1 }}: ({{ particle.x.toFixed(2) }}, {{ particle.y.toFixed(2) }}
- , {{ particle.z.toFixed(2) }})
-
diff --git a/frontend/src/app/particles/components/frames/frames.component.scss b/frontend/src/app/particles/components/frames/frames.component.scss
index 4e9c57b..0d9a8ae 100644
--- a/frontend/src/app/particles/components/frames/frames.component.scss
+++ b/frontend/src/app/particles/components/frames/frames.component.scss
@@ -17,10 +17,14 @@
.particle-item {
display: flex;
- justify-content: space-between;
align-items: center;
padding: 8px;
border-bottom: 1px solid #eee;
+ gap: 10px;
+}
+
+.particle-item-text {
+ flex-grow: 1;
}
.particle-item:last-child {
diff --git a/frontend/src/app/particles/components/frames/frames.component.ts b/frontend/src/app/particles/components/frames/frames.component.ts
index 484ede0..55ac39f 100644
--- a/frontend/src/app/particles/components/frames/frames.component.ts
+++ b/frontend/src/app/particles/components/frames/frames.component.ts
@@ -83,4 +83,7 @@ export class FramesComponent {
}
+ public highlightParticle(frameId: string, i: number) {
+ this.particleManagerService.highlightParticle(frameId, i);
+ }
}
diff --git a/frontend/src/app/particles/services/particle-manager.service.ts b/frontend/src/app/particles/services/particle-manager.service.ts
index 2afabb7..f14c5e8 100644
--- a/frontend/src/app/particles/services/particle-manager.service.ts
+++ b/frontend/src/app/particles/services/particle-manager.service.ts
@@ -1,7 +1,7 @@
-import { Injectable } from '@angular/core';
+import {Injectable} from '@angular/core';
import * as THREE from 'three';
-import { RendererService } from './renderer.service';
-import { ParticleData, ParticleInfo, ParticleType } from '../models/particle.model';
+import {RendererService} from './renderer.service';
+import {ParticleData, ParticleInfo, ParticleType} from '../models/particle.model';
/**
* Service responsible for managing particles in the scene
@@ -32,7 +32,8 @@ export class ParticleManagerService {
private frames: string[] = ['frame1'];
private selectedColor: string = '#ff0000';
- constructor(private rendererService: RendererService) {}
+ constructor(private rendererService: RendererService) {
+ }
/**
* Adds a particle at the specified position
@@ -120,6 +121,51 @@ export class ParticleManagerService {
}
}
+ highlightParticle(frameId: string, index: number): void {
+ if (!(this.particleData.frames[frameId] && this.particleData.frames[frameId].length > index)) {
+ return;
+ }
+ const particleInfo = this.particleData.frames[frameId][index];
+ const colorParts = particleInfo.color.split(',');
+ const color = new THREE.Color(
+ parseFloat(colorParts[0]),
+ parseFloat(colorParts[1]),
+ parseFloat(colorParts[2])
+ );
+ const particleMaterial = new THREE.MeshBasicMaterial({color});
+ const particleGeometry = new THREE.SphereGeometry(0.03, 16, 16);
+ const particleMesh = new THREE.Mesh(particleGeometry, particleMaterial);
+ particleMesh.position.set(particleInfo.x, particleInfo.y, particleInfo.z);
+ this.rendererService.scene.add(particleMesh);
+ this.particles.push(particleMesh);
+ this.animatePulse(particleMesh, 3, () => {
+ this.rendererService.scene.remove(particleMesh);
+ this.clearParticleVisuals();
+ this.renderFrameParticles(this.currentFrame);
+ });
+ }
+
+ private animatePulse(mesh: THREE.Mesh, cycles: number, onComplete: () => void): void {
+ const duration = 300;
+ const maxScale = 0.08 / 0.03;
+ const startTime = performance.now();
+
+ const animate = (time: number) => {
+ const elapsed = (time - startTime) % duration;
+ const t = elapsed / (duration / 2);
+ const scaleFactor = t <= 1 ? 1 + (maxScale - 1) * t : maxScale - (maxScale - 1) * (t - 1);
+ mesh.scale.setScalar(scaleFactor);
+
+ if (time - startTime >= duration * cycles) {
+ onComplete();
+ } else {
+ requestAnimationFrame(animate);
+ }
+ };
+
+ requestAnimationFrame(animate);
+ }
+
/**
* Sets the selected color for new particles
*/