debut de redimensionnement des blocs de la timeline

This commit is contained in:
2024-10-15 07:47:57 +00:00
parent 46acc3e88f
commit 98c6dff4bf
3 changed files with 139 additions and 3 deletions

View File

@@ -140,6 +140,7 @@ canvas {
height: 23px;
background-color: hsla(240, 100%, 50%, 0.308);
border: 2px solid black;
border-radius: 4px;
cursor: move;
font-family: Arial, Helvetica, sans-serif;
font-size: 12px;
@@ -154,3 +155,20 @@ canvas {
background-color: hsl(0, 1%, 41%); /* Couleur du trait de temps */
left: 0; /* Point de départ du trait */
}
.handle-left, .handle-right {
position: absolute;
top: 0;
width: 20px;
height: 100%;
background-color: hsla(240, 100%, 50%, 0.507);;
cursor: ew-resize;
}
.handle-left {
left: 0;
}
.handle-right {
right: 0;
}

View File

@@ -72,6 +72,18 @@
[style.width]="calculateBlockWidth(stepPlayer)"
(mousedown)="onTimelineBlockMouseDown($event, player, i)">
{{ i + 1 }}
<div class="handle-left"
(mousedown)="onHandleMouseDown($event, 'left')"
(mousemove)="onHandleMouseMove($event)"
(mouseup)="onHandleMouseUp()">
<!-- poignée gauche -->
</div>
<div class="handle-right"
(mousedown)="onHandleMouseDown($event, 'right')"
(mousemove)="onHandleMouseMove($event)"
(mouseup)="onHandleMouseUp()">
<!-- poignée droite -->
</div>
</div>
<div class="time-indicator" id="time-indicator">
<!-- Trait de visualisation -->

View File

@@ -1,7 +1,8 @@
import { Component, ViewChild, ElementRef, HostListener } from '@angular/core';
import { Component, ViewChild, Renderer2, ElementRef, HostListener } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { C } from '@angular/cdk/keycodes';
import { CdkPortal } from '@angular/cdk/portal';
interface TimelineStep {
startTime: number; // Le temps de début en millisecondes
@@ -107,6 +108,12 @@ export class FootballFieldComponent {
private isPlaying: boolean = false;
// Timestamp de début de l'animation
private animationStartTime: number = 0;
private isResizingLeft: boolean = false;
private isResizingRight: boolean = false;
private currentBlock: HTMLElement | null = null;
private initialMouseX:number = 0;
private initialBlockLeft:number = 0;
private initialBlockWidth:number = 0;
public playerCount: number = 8; // Nombre de joueurs par défaut
public plotCount: number = 2; // Nombre de plots par défaut
@@ -143,6 +150,8 @@ export class FootballFieldComponent {
// un bloc sur la timeline.
public dragOffsetX: number = 0;
constructor(private renderer: Renderer2, private el: ElementRef) {}
ngOnInit() {
this.ctx = this.canvas.nativeElement.getContext('2d')!;
this.drawField();
@@ -653,6 +662,7 @@ export class FootballFieldComponent {
endY: this.endY,
duration: 1000 // Durée d'animation arbitraire, peut être ajustée
});
console.log("timeline player:", this.selectedPlayer.steps);
// Initialiser l'index à l'étape précédente
this.selectedPlayer.currentStepIndex = this.selectedPlayer.steps.length - 1;
@@ -700,7 +710,30 @@ export class FootballFieldComponent {
}
}
}
/*
private addHandleListener() {
// Utiliser Renderer2 pour accéder aux éléments DOM en toute sécurité
const timelineBlocks = this.el.nativeElement.querySelectorAll('.timeline-block');
console.log("timelineBlocks:", timelineBlocks);
timelineBlocks.forEach((block: HTMLElement) => {
console.log("PLOP1");
const leftHandle = block.querySelector('.handle-left');
const rightHandle = block.querySelector('.handle-right');
// Attacher les événements de redimensionnement
if (leftHandle) {
this.renderer.listen(leftHandle, 'mousedown', (event: MouseEvent) => this.onResizeStart(event, 'left', block));
}
if (rightHandle) {
this.renderer.listen(rightHandle, 'mousedown', (event: MouseEvent) => this.onResizeStart(event, 'right', block));
}
});
// Attacher les événements pour le document entier
this.renderer.listen(document, 'mousemove', this.onMouseMove.bind(this));
this.renderer.listen(document, 'mouseup', this.onMouseUp.bind(this));
}
*/
// Commencer a déplacer un élément du canvas
startDragging(x:number, y:number) {
if (this.isInsideCircle(this.ball.design, x, y)) {
@@ -938,6 +971,80 @@ export class FootballFieldComponent {
/* GESTION DE LA TIMELINE */
onHandleMouseMove(event: MouseEvent) {
console.log("[onHandleMouseMove]");
if (!this.currentBlock) return;
const deltaX = event.clientX - this.initialMouseX;
if (this.isResizingLeft) {
const newLeft = this.initialBlockLeft + deltaX;
const newWidth = this.initialBlockWidth - deltaX;
if (newWidth > 10) { // Empêcher une largeur trop petite
this.currentBlock.style.left = `${newLeft}px`;
this.currentBlock.style.width = `${newWidth}px`;
this.updateTimelineData(); // Mettre à jour les données de la timeline
}
} else if (this.isResizingRight) {
const newWidth = this.initialBlockWidth + deltaX;
if (newWidth > 10) { // Empêcher une largeur trop petite
this.currentBlock.style.width = `${newWidth}px`;
this.updateTimelineData(); // Mettre à jour les données de la timeline
}
}
}
onHandleMouseUp() {
console.log("[onHandleMouseUp]");
this.isResizingLeft = false;
this.isResizingRight = false;
this.currentBlock = null;
}
onHandleMouseDown(event: MouseEvent, direction: 'left' | 'right') {
console.log("[onHandleMouseDown]");
// Empêche le comportement par défaut (sélection de texte)
event.preventDefault();
//this.currentBlock = block;
// Position initiale de la souris
//this.initialMouseX = event.clientX;
// Position initiale du bloc
//this.initialBlockLeft = block.offsetLeft;
// Largeur initiale du bloc
//this.initialBlockWidth = block.offsetWidth;
//console.log("[onResizeStart] (",this.initialMouseX, " - ", this.currentBlock);
//if (direction === 'left') {
// this.isResizingLeft = true;
//} else if (direction === 'right') {
// this.isResizingRight = true;
//}
}
updateTimelineData() {
if (!this.currentBlock) return;
const blockId = this.currentBlock.id;
const blockLeft = this.currentBlock.offsetLeft;
const blockWidth = this.currentBlock.offsetWidth;
// Conversion des positions en temps sur la timeline (ex: 1px = 10ms)
const startTime = blockLeft * 10;
const endTime = (blockLeft + blockWidth) * 10;
// Mettre à jour les données du bloc (par exemple pour un joueur)
const timelineStep = this.getTimelineStepById(blockId);
if (timelineStep) {
timelineStep.startTime = startTime;
timelineStep.endTime = endTime;
}
}
getTimelineStepById(blockId: string): TimelineStep | null {
// Trouver le bloc correspondant aux données
// Cette fonction est un exemple. Adapte-la selon la manière dont tu stockes tes données
return this.players.find(player => `block-${player.id}` === blockId)?.steps[0] || null;
}
getMousePosOnTimeline(event: MouseEvent): { x: number } {
// Récupérer l'élément avec la classe 'timeline'
const timelineElement = document.querySelector('.timeline') as HTMLElement;
@@ -996,7 +1103,6 @@ export class FootballFieldComponent {
}
onTLBallMouseMove(event: MouseEvent) {
console.log("[onTLBallMouseMove]");
if (this.isTimelineDragging && this.draggedTimelineBall) {
const { x } = this.getMousePosOnTimeline(event);
@@ -1193,7 +1299,7 @@ export class FootballFieldComponent {
getTotalTimelineDuration(): number {
// Calculer la durée totale de la timeline, par exemple basée sur la durée totale de l'animation
return 20000; // Par exemple, 10 000 ms pour une timeline de 10 secondes
return 10000; // Par exemple, 10 000 ms pour une timeline de 10 secondes
}
playTimeline() {