correction bug sur timeline

This commit is contained in:
2024-10-10 17:43:59 +02:00
parent 999c512aa1
commit 245c9acf7a
4 changed files with 124 additions and 61 deletions

View File

@@ -1,9 +1,10 @@
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { FootballFieldComponent } from './football-field/football-field.component';
@NgModule({
declarations: [
FootballFieldComponent
],
imports: [
FormsModule
]
})
export class AppModule {}

View File

@@ -76,17 +76,24 @@ canvas {
.timeline {
position: relative;
width: 100%;
height: 20px;
height: 25px;
background-color: #f0f0f0;
border: 1px solid #ccc;
display: flex;
align-items: center;
align-items: right;
}
.timeline-name {
width: 10%;
display: flex;
align-items: left;
margin-right: 10px;
}
.timeline-block {
position: absolute;
height: 15px;
background-color: blue;
height: 25px;
background-color: hsla(240, 100%, 50%, 0.308);
border: 1px solid black;
cursor: move;
}

View File

@@ -64,32 +64,33 @@
<div class="timeline-container">
<div *ngFor="let player of players" class="player-timeline">
<span>{{ player.id }}</span>
<div class="timeline" (mousedown)="onTimelineMouseDown($event, player)">
<span class="timeline-name">Joueur {{ player.id }}</span>
<div class="timeline" (mousedown)="onTimelineMouseDown($event, player)"
(mousemove)="onTimelineMouseMove($event)"
(mouseup)="onTimelineMouseUp()">
<div *ngFor="let step of player.timeline; let i = index"
class="timeline-block"
[style.left]="calculateLeftPosition(step)"
[style.width]="calculateBlockWidth(step)"
(mousedown)="onTimelineBlockMouseDown($event, player, i)"
(mousemove)="onMouseMove($event)"
(mouseup)="onMouseUp()">
[style.left]="calculateLeftPosition(step)"
[style.width]="calculateBlockWidth(step)"
(mousedown)="onTimelineBlockMouseDown($event, player, i)">
</div>
</div>
</div>
</div>
</div>
<div class="timeline">
<div class="timeline-player">
<h3>Timeline du joueur sélectionné</h3>
<div *ngIf="selectedPlayer">
<ul>
<li *ngFor="let step of selectedPlayer.timeline; let i = index">
Étape {{ i + 1 }} : Départ ({{ step.startX }}, {{ step.startY }}), Arrivée ({{ step.endX }}, {{ step.endY }}), Durée : {{ step.duration }}
Étape {{ i + 1 }} : Départ ({{ step.startX }}, {{ step.startY }}), Arrivée ({{ step.endX }}, {{ step.endY }}), Durée : ({{ step.startTime }}, {{ step.endTime }}: {{ step.duration }})
</li>
</ul>
</div>
</div>
<div class="debug">
<p>Debug Info: {{ debugInfo }}</p>
<h3>Debug Info</h3>
<p>{{ debugInfo }}</p>
</div>
<!-- <div class="controls">
<button (click)="clearDrawings()">Effacer les dessins</button>

View File

@@ -82,7 +82,7 @@ export class FootballFieldComponent {
// '#0000ff', '#ffff00',
// '#ff00ff', '#00ffff',
// '#000000', '#808080',
// '#ffa500', '#8a2be2'];
// '#ffa500', '#8a2be2'];
//public selectedColor: string = this.colors[0]; // Couleur sélectionné par défaut (rouge)
// Options de forme
//public selectedShape: string = 'none'; // Par défaut, aucune forme
@@ -94,21 +94,21 @@ export class FootballFieldComponent {
public plots: Circle[] = [];
public piquets: Rectangle[] = [];
public ball: Circle = { id: 0,
x:400,
y:300,
number:1,
radius:10,
isDragging:false,
vx:0,
vy:0,
destinationX: null,
destinationY: null,
isMoving:false,
progress: 0,
startX: 150,
startY: 150,
timeline: null,
currentStepIndex: 0 };
x:400,
y:300,
number:1,
radius:10,
isDragging:false,
vx:0,
vy:0,
destinationX: null,
destinationY: null,
isMoving:false,
progress: 0,
startX: 150,
startY: 150,
timeline: null,
currentStepIndex: 0 };
public selectedPlayer: Circle | null = null;
public isDrawingLine: boolean = false;
public loopAnimation: boolean = false; // Pour répéter l'animation
@@ -122,7 +122,7 @@ export class FootballFieldComponent {
// La largeur totale de la timeline en pixels.
// Cela représente la taille visuelle de la timeline dans laquelle
// les différents étapes de mouvement d'un élément sont affichés.
public timelineWidth: number = 800;
public timelineWidth: number = 722;
// Décalage horizontal en pixels utilisé lorsque vous commencez à déplacer
// un bloc sur la timeline.
public dragOffsetX: number = 0;
@@ -251,6 +251,17 @@ export class FootballFieldComponent {
// Temps actuel
const currentTime = performance.now();
/*
// Vérifier si le temps actuel correspond à l'intervalle de cette étape
if (currentTime >= step.startTime && currentTime <= step.endTime) {
const t = (currentTime - step.startTime) / (step.endTime - step.startTime);
player.x = (1 - t) * step.startX + t * step.endX;
player.y = (1 - t) * step.startY + t * step.endY;
} else if (currentTime > step.endTime) {
player.currentStepIndex++;
}
*/
if (player.progress >= 1) {
player.progress = 0; // Réinitialiser la progression
player.x = step.endX;
@@ -274,10 +285,12 @@ export class FootballFieldComponent {
// Mettre à jour debugInfo avec les positions des joueurs et du ballon
private updateDebugInfo() {
const playerPositions = this.players.map((player, index) => `Joueur ${index + 1}: (${player.x.toFixed(1)}, ${player.y.toFixed(1)})`).join(', ');
const ballPosition = `Ballon: (${this.ball.x.toFixed(1)}, ${this.ball.y.toFixed(1)})`;
const playerPositions = this.players.map((player, index) =>
`Joueur ${index + 1}: (${player.x.toFixed(1)}, ${player.y.toFixed(1)})`
).join(', ');
const ballPosition = `Ballon: (${this.ball.x.toFixed(1)}, ${this.ball.y.toFixed(1)})`;
this.debugInfo = `${playerPositions}, ${ballPosition}`;
this.debugInfo = `${playerPositions}, ${ballPosition}`;
}
// Créer les cercles nuerotes representant les joueurs
@@ -493,16 +506,23 @@ export class FootballFieldComponent {
this.endY = y;
this.isDrawingLine = false;
// Ajouter l'étape dans la timeline du joueur
console.log("timeline:", this.selectedPlayer.timeline);
let prevStartTime:number = 0;
if (this.selectedPlayer.timeline && this.selectedPlayer.timeline.length > 0) {
prevStartTime = this.selectedPlayer.timeline[this.selectedPlayer.timeline.length - 1].endTime;
} else {
prevStartTime = 0;
}
this.selectedPlayer.timeline.push({
startTime: 0,
endTime: 1000,
startTime: prevStartTime,
endTime: prevStartTime + 200,
startX: this.startX,
startY: this.startY,
endX: this.endX,
endY: this.endY,
duration: 100 // Durée d'animation arbitraire, peut être ajustée
duration: 200 // Durée d'animation arbitraire, peut être ajustée
});
console.log("timeline:", this.selectedPlayer.timeline);
this.selectedPlayer.currentStepIndex = 0; // Réinitialiser au début de la timeline
this.startAnimation();
}
@@ -898,17 +918,25 @@ export class FootballFieldComponent {
/* GESTION DE LA TIMELINE */
getMousePosOnTimeline(event: MouseEvent): { x: number } {
const timelineRect = (event.target as HTMLElement).getBoundingClientRect();
return {
x: event.clientX - timelineRect.left // Position X par rapport à la timeline
};
// Récupérer l'élément avec la classe 'timeline'
const timelineElement = document.querySelector('.timeline') as HTMLElement;
if (timelineElement) {
// Récupérer la position de la timeline relative à la fenêtre
const timelineRect = timelineElement.getBoundingClientRect();
// Position X par rapport à la timeline
//console.log("[getMousePosOnTimeline] timeline rectangle left:", timelineRect.left, " - x:", event.clientX, "- res: ", event.clientX - timelineRect.left);
// Calculer la position X relative de la souris par rapport à la timeline
return { x: event.clientX - timelineRect.left };
}
return { x: 0 };
}
calculateBlockPixelPosition(time: number): number {
// La durée totale de la timeline
const totalDuration = this.getTotalTimelineDuration();
// La largeur de la timeline en pixels (par exemple, 1000px)
const timelineWidth = this.timelineWidth;
const totalDuration = this.getTotalTimelineDuration();
// La longueur de la timeline en pixels (par exemple, 1000px)
const timelineWidth = this.timelineWidth;
// La durée totale de l'animation en millisecondes
return (time / totalDuration) * timelineWidth;
}
@@ -920,52 +948,69 @@ export class FootballFieldComponent {
// Chercher si un bloc (une étape du joueur) a été cliqué
for (let i = 0; i < player.timeline.length; i++) {
const step = player.timeline[i];
//console.log("[OnTimelineMouseDown | Joueur",player.id,"] - Timeline[",i,"]:", step);
// Calculer la position du bloc en pixels sur la timeline
const blockStartX = this.calculateBlockPixelPosition(step.startTime);
const blockEndX = this.calculateBlockPixelPosition(step.endTime);
console.log("[OnTimelineMouseDown | Joueur",player.id," | Block:",
i+1,"] x:",
x,
" - blockStartX:", blockStartX,
" - blockEndX:", blockEndX);
// Si la souris clique dans un bloc
if (x >= blockStartX && x <= blockEndX) {
console.log("clique dans un bloc !");
// Début du déplacement du bloc
this.isTimelineDragging = true;
this.draggedTimelinePlayer = player;
this.draggedTimelineIndex = i;
// Garder une référence pour un déplacement fluide
this.dragOffsetX = x - blockStartX;
this.dragOffsetX = x - blockStartX;
console.log("[OnTimelineMouseDown | Joueur",player.id,"] clique dans un bloc",
i+1,
" ! dragOffsetX:", this.dragOffsetX);
break;
}
}
}
onTimelineBlockMouseDown(event: MouseEvent, player: Circle, index: number) {
console.log("onTimelineBlockMouseDown");
console.log("[onTimelineBlockMouseDown] index:", index);
this.isTimelineDragging = true;
this.draggedTimelinePlayer = player;
this.draggedTimelineIndex = index;
}
onMouseMove(event: MouseEvent) {
onTimelineMouseMove(event: MouseEvent) {
if (this.isTimelineDragging && this.draggedTimelinePlayer) {
console.log("onMouseMove");
const { x } = this.getMousePos(event);
//const { x } = this.getMousePos(event);
const { x } = this.getMousePosOnTimeline(event);
// Calculer la nouvelle position du bloc
const newStartX = x - this.dragOffsetX;
const totalDuration = this.getTotalTimelineDuration();
const newStartTime = (x / this.canvas.nativeElement.width) * totalDuration;
//const newStartTime = Math.floor((newStartX / this.canvas.nativeElement.width) * totalDuration);
const newStartTime = Math.floor((newStartX / this.timelineWidth) * totalDuration);
console.log("[onTimelineMouseMove] - x:",x,
" - newStartX:", newStartX,
" - newStartTime:", newStartTime);
// Mettre à jour l'étape avec la nouvelle position
const step = this.draggedTimelinePlayer.timeline[this.draggedTimelineIndex];
step.startTime = Math.max(0, newStartTime); // Ne pas permettre les valeurs négatives
if (step.endTime < this.getTotalTimelineDuration()) {
step.startTime = Math.max(0, newStartTime); // Ne pas permettre les valeurs négatives
}
step.endTime = Math.max(0, newStartTime + step.duration); // Ne pas permettre les valeurs négatives
/*
// Ajuster la position de fin si nécessaire
if (this.draggedTimelineIndex > 0) {
const previousStep = this.draggedTimelinePlayer.timeline[this.draggedTimelineIndex - 1];
previousStep.endTime = step.startTime;
}
*/
}
}
onMouseUp() {
onTimelineMouseUp() {
console.log("onMouseUp");
if (this.isTimelineDragging) {
this.isTimelineDragging = false;
@@ -977,12 +1022,21 @@ export class FootballFieldComponent {
calculateLeftPosition(step: TimelineStep): string {
const totalDuration = this.getTotalTimelineDuration();
const left = (step.startTime / totalDuration) * 100;
//console.log("[calculateLeftPosition], left:", left, " - startTime:", step.startTime);
return `${left}%`;
}
calculateBlockWidth(step: TimelineStep): string {
const totalDuration = this.getTotalTimelineDuration();
const width = ((step.endTime - step.startTime) / totalDuration) * 100;
/*
if (step.endTime >= step.startTime) {
const width = ((step.endTime - step.startTime) / totalDuration) * 100;
console.log("block width:", width);
return `${width}%`;
}
return "0";
*/
const width = (step.duration / totalDuration) * 100;
return `${width}%`;
}