update du code source
This commit is contained in:
@@ -92,5 +92,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"cli": {
|
||||||
|
"analytics": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "football-drawing",
|
"name": "football-drawing",
|
||||||
"version": "0.0.0",
|
"version": "0.1.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "football-drawing",
|
"name": "football-drawing",
|
||||||
"version": "0.0.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "^18.2.0",
|
"@angular/animations": "^18.2.0",
|
||||||
"@angular/cdk": "^18.2.6",
|
"@angular/cdk": "^18.2.6",
|
||||||
|
|||||||
@@ -1,15 +1,34 @@
|
|||||||
<div class="football-container">
|
<div class="football-container">
|
||||||
<!-- Sélecteur de couleurs au-dessus du canvas -->
|
<!-- Sélecteur de couleurs au-dessus du canvas -->
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<div class="color-palette">
|
<!-- <div class="color-palette">
|
||||||
<div *ngFor="let color of colors" [style.background]="color" (click)="setColor(color)" class="color-box" [class.selected]="color === selectedColor">
|
<div *ngFor="let color of colors" [style.background]="color" (click)="setColor(color)" class="color-box" [class.selected]="color === selectedColor">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
|
<!-- Saisie du nombre de joueurs -->
|
||||||
|
<div class="player-count">
|
||||||
|
<label for="playerCount">Nombre de joueurs : </label>
|
||||||
|
<input type="number" id="playerCount" [(ngModel)]="playerCount" min="1" max="25" (change)="updatePlayers()">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Saisie du nombre de plots -->
|
||||||
|
<div class="plot-count">
|
||||||
|
<label for="plotCount">Nombre de plots : </label>
|
||||||
|
<input type="number" id="plotCount" [(ngModel)]="plotCount" min="1" max="50" (change)="updatePlots()">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Saisie du nombre de plots -->
|
||||||
|
<div class="piquet-count">
|
||||||
|
<label for="piquetCount">Nombre de piquets : </label>
|
||||||
|
<input type="number" id="piquetCount" [(ngModel)]="piquetCount" min="1" max="20" (change)="updatePiquets()">
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Bouton pour réinitialiser le dessin -->
|
<!-- Bouton pour réinitialiser le dessin -->
|
||||||
<button (click)="clearCanvas()" class="clear-button">Réinitialiser</button>
|
<button (click)="clearCanvas()" class="clear-button">Réinitialiser</button>
|
||||||
|
|
||||||
<!-- Sélection de forme -->
|
<!-- Sélection de forme -->
|
||||||
<div class="shape-selector">
|
<!-- <div class="shape-selector">
|
||||||
<label for="shape">Forme :</label>
|
<label for="shape">Forme :</label>
|
||||||
<select id="shape" [(ngModel)]="selectedShape">
|
<select id="shape" [(ngModel)]="selectedShape">
|
||||||
<option value="none">Aucune</option>
|
<option value="none">Aucune</option>
|
||||||
@@ -17,14 +36,20 @@
|
|||||||
<option value="circle">Cercle</option>
|
<option value="circle">Cercle</option>
|
||||||
<option value="line">Ligne</option>
|
<option value="line">Ligne</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<canvas #canvas width="800" height="600"
|
<!-- <canvas #canvas width="800" height="600"
|
||||||
(mousedown)="startDrawing($event)"
|
(mousedown)="startDrawing($event)"
|
||||||
(mousemove)="draw($event)"
|
(mousemove)="draw($event)"
|
||||||
(mouseup)="stopDrawing()">
|
(mouseup)="stopDrawing()">
|
||||||
Your browser does not support the canvas element.
|
Your browser does not support the canvas element.
|
||||||
|
</canvas> -->
|
||||||
|
<canvas #canvas width="800" height="600"
|
||||||
|
(mousedown)="startDragging($event)"
|
||||||
|
(mousemove)="drag($event)"
|
||||||
|
(mouseup)="stopDragging()">
|
||||||
|
Votre navigateur ne supporte pas l'élément canvas.
|
||||||
</canvas>
|
</canvas>
|
||||||
<!-- <div class="controls">
|
<!-- <div class="controls">
|
||||||
<button (click)="clearDrawings()">Effacer les dessins</button>
|
<button (click)="clearDrawings()">Effacer les dessins</button>
|
||||||
|
|||||||
@@ -2,6 +2,22 @@ import { Component, ViewChild, ElementRef, HostListener } from '@angular/core';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
interface Circle {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
number: number;
|
||||||
|
radius: number;
|
||||||
|
isDragging: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Rectangle {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
isDragging: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-football-field',
|
selector: 'app-football-field',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
@@ -20,6 +36,21 @@ export class FootballFieldComponent {
|
|||||||
private lastY = 0;
|
private lastY = 0;
|
||||||
private startX = 0;
|
private startX = 0;
|
||||||
private startY = 0;
|
private startY = 0;
|
||||||
|
public playerCount: number = 2; // Nombre de joueurs par défaut
|
||||||
|
public plotCount: number = 1; // Nombre de plots par défaut
|
||||||
|
public piquetCount: number = 1; // Nombre de plots par défaut
|
||||||
|
public ballCount: number = 1; // Nombre de ballons par defaut
|
||||||
|
public players: Circle[] = [];
|
||||||
|
public plots: Circle[] = [];
|
||||||
|
public piquets: Rectangle[] = [];
|
||||||
|
public ball: Circle = { x:400, y:300, number:1, radius:8, isDragging:false };
|
||||||
|
private draggingPlayer: Circle | null = null;
|
||||||
|
private draggingPlot: Circle | null = null;
|
||||||
|
private draggingPiquet: Rectangle | null = null;
|
||||||
|
private draggingElement: any = null;
|
||||||
|
private attachedToPlayer: boolean = false; // indique si le ballon est attache a un joueur
|
||||||
|
private offsetX: number = 0;
|
||||||
|
private offsetY: number = 0;
|
||||||
|
|
||||||
public colors: string[] = ['#ff0000', '#00ff00',
|
public colors: string[] = ['#ff0000', '#00ff00',
|
||||||
'#0000ff', '#ffff00',
|
'#0000ff', '#ffff00',
|
||||||
@@ -33,6 +64,9 @@ export class FootballFieldComponent {
|
|||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.ctx = this.canvas.nativeElement.getContext('2d')!;
|
this.ctx = this.canvas.nativeElement.getContext('2d')!;
|
||||||
this.drawField();
|
this.drawField();
|
||||||
|
this.createPlayers();
|
||||||
|
this.createPlots();
|
||||||
|
this.createPiquets();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dessine le terrain de football
|
// Dessine le terrain de football
|
||||||
@@ -100,6 +134,238 @@ export class FootballFieldComponent {
|
|||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(10, canvas.height - 10 , 20, Math.PI * 3/2, Math.PI * 2 );
|
ctx.arc(10, canvas.height - 10 , 20, Math.PI * 3/2, Math.PI * 2 );
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
|
|
||||||
|
// Dessiner les cercles numerotes
|
||||||
|
this.drawPlayers();
|
||||||
|
this.drawPlots();
|
||||||
|
this.drawPiquets();
|
||||||
|
this.drawBall();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Créer les cercles nuerotes representant les joueurs
|
||||||
|
private createPlayers() {
|
||||||
|
this.players = [];
|
||||||
|
const radius = 15; // Rayon des cercles
|
||||||
|
for (let i = 0; i < this.playerCount; i++) {
|
||||||
|
const x = i * (2 * radius) + radius;
|
||||||
|
const y = radius;
|
||||||
|
this.players.push({ x, y, number: i + 1, radius, isDragging: false });
|
||||||
|
}
|
||||||
|
this.drawField();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Créer les cerclesrepresentant les plots
|
||||||
|
private createPlots() {
|
||||||
|
this.plots = [];
|
||||||
|
const radius = 10; // Rayon des cercles
|
||||||
|
for (let i = 0; i < this.plotCount; i++) {
|
||||||
|
const x = (this.canvas.nativeElement.width - radius) - (i) * (2 * radius);
|
||||||
|
const y = radius;
|
||||||
|
this.plots.push({ x, y, number: i + 1, radius, isDragging: false });
|
||||||
|
}
|
||||||
|
this.drawField();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Créer lespiquets
|
||||||
|
private createPiquets() {
|
||||||
|
this.piquets = [];
|
||||||
|
for (let i = 0; i < this.piquetCount; i++) {
|
||||||
|
const x = 300;
|
||||||
|
const y = 400;
|
||||||
|
const width = 7;
|
||||||
|
const height = 70;
|
||||||
|
this.piquets.push({ x, y, width, height, isDragging: false });
|
||||||
|
}
|
||||||
|
this.drawField();
|
||||||
|
}
|
||||||
|
// Mettre a jour les joueurs quand le nombre change
|
||||||
|
updatePlayers() {
|
||||||
|
this.createPlayers();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mettre a jour les plots quand le nombre change
|
||||||
|
updatePlots() {
|
||||||
|
this.createPlots();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mettre a jour les plots quand le nombre change
|
||||||
|
updatePiquets() {
|
||||||
|
this.createPiquets();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dessiner les cercles numéroe representant les joueurs
|
||||||
|
private drawPlayers() {
|
||||||
|
this.players.forEach(circle => {
|
||||||
|
this.drawPlayer(circle);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dessiner les cercles representant les plots
|
||||||
|
private drawPlots() {
|
||||||
|
this.plots.forEach(circle => {
|
||||||
|
this.drawPlot(circle);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private drawPiquets() {
|
||||||
|
this.piquets.forEach(rectangle => {
|
||||||
|
this.drawPiquet(rectangle);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dessiner un ballon
|
||||||
|
private drawBall() {
|
||||||
|
const ctx = this.ctx;
|
||||||
|
|
||||||
|
// Dessiner le cercle
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(this.ball.x, this.ball.y, this.ball.radius, 0, Math.PI * 2);
|
||||||
|
ctx.fillStyle = '#ffffff';
|
||||||
|
ctx.fill();
|
||||||
|
ctx.strokeStyle = '#000000';
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dessiner un plot
|
||||||
|
private drawPlot(circle: Circle) {
|
||||||
|
const ctx = this.ctx;
|
||||||
|
|
||||||
|
// Dessiner le cercle
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2);
|
||||||
|
ctx.fillStyle = '#ffa500';
|
||||||
|
ctx.fill();
|
||||||
|
ctx.strokeStyle = '#ff4500';
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dessiner un piquet
|
||||||
|
private drawPiquet(rectangle: Rectangle) {
|
||||||
|
const ctx = this.ctx;
|
||||||
|
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillStyle = '#ff0000';
|
||||||
|
ctx.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
|
||||||
|
ctx.strokeStyle = '#000000';
|
||||||
|
ctx.strokeRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dessiner un joueur avec un numér
|
||||||
|
private drawPlayer(circle: Circle) {
|
||||||
|
const ctx = this.ctx;
|
||||||
|
|
||||||
|
// Dessiner le cercle
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2);
|
||||||
|
ctx.fillStyle = '#ffff00';
|
||||||
|
ctx.fill();
|
||||||
|
ctx.strokeStyle = '#000000';
|
||||||
|
ctx.stroke();
|
||||||
|
|
||||||
|
// Ajouter le numéro dans le cercle
|
||||||
|
ctx.fillStyle = '#000000';
|
||||||
|
ctx.font = 'bold 12px Arial';
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
ctx.textBaseline = 'middle';
|
||||||
|
ctx.fillText(circle.number.toString(), circle.x, circle.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commencer a déplacer un cercle
|
||||||
|
startDragging(event: MouseEvent) {
|
||||||
|
const { x, y } = this.getMousePos(event);
|
||||||
|
this.draggingElement = this.plots.find(plot => this.isInsideCircle(plot, x, y)) ||
|
||||||
|
this.piquets.find(piquet => this.isInsideRectangle(piquet, x, y)) ||
|
||||||
|
(this.isInsideCircle(this.ball, x, y) ? this.ball : null);
|
||||||
|
this.draggingPlayer = this.players.find(circle => {
|
||||||
|
return this.isInsideCircle(circle, x, y);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.draggingElement) {
|
||||||
|
this.draggingElement.isDragging = true;
|
||||||
|
this.offsetX = x - this.draggingElement.x;
|
||||||
|
this.offsetY = y - this.draggingElement.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.draggingPlayer) {
|
||||||
|
this.draggingPlayer.isDragging = true;
|
||||||
|
this.offsetX = x - this.draggingPlayer.x;
|
||||||
|
this.offsetY = y - this.draggingPlayer.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier si le joueur touche le ballon
|
||||||
|
if (this.draggingPlayer && this.isInsideCircle(this.ball, this.draggingPlayer.x, this.draggingPlayer.y)) {
|
||||||
|
this.attachedToPlayer = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Déplacer le cercle sélectionné
|
||||||
|
drag(event: MouseEvent) {
|
||||||
|
const { x, y } = this.getMousePos(event);
|
||||||
|
|
||||||
|
if (this.draggingPlayer && this.draggingPlayer.isDragging) {
|
||||||
|
this.draggingPlayer.x = x - this.offsetX;
|
||||||
|
this.draggingPlayer.y = y - this.offsetY;
|
||||||
|
|
||||||
|
// Si le ballon est attaché au joueur deplacer le ballon avec lui en calculant
|
||||||
|
// la tangente
|
||||||
|
if (this.attachedToPlayer) {
|
||||||
|
this.updateBallPositionOnTangent();
|
||||||
|
}
|
||||||
|
this.drawField();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.draggingElement && this.draggingElement.isDragging) {
|
||||||
|
this.draggingElement.x = x - this.offsetX;
|
||||||
|
this.draggingElement.y = y - this.offsetY;
|
||||||
|
this.drawField();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arrêter de déplacer le cercle
|
||||||
|
stopDragging() {
|
||||||
|
if (this.draggingPlayer) {
|
||||||
|
this.draggingPlayer.isDragging = false;
|
||||||
|
this.draggingPlayer = null;
|
||||||
|
this.attachedToPlayer = false; // Détacher le ballon après avoirelache le joueur
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.draggingElement) {
|
||||||
|
this.draggingElement.isDragging = false;
|
||||||
|
this.draggingElement = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculer la nouvelle position du ballon a la tangente du joueur
|
||||||
|
private updateBallPositionOnTangent() {
|
||||||
|
const player = this.draggingPlayer;
|
||||||
|
if (!player) return;
|
||||||
|
|
||||||
|
const dx = this.ball.x - this.draggingPlayer.x;
|
||||||
|
const dy = this.ball.y - this.draggingPlayer.y;
|
||||||
|
const distance = Math.sqrt(dx * dy + dy * dy); // Distance entre le joueur et le ballon
|
||||||
|
const angle = Math.atan2(dy, dx); // Calculer l'angle entre le joueur et le ballon
|
||||||
|
|
||||||
|
// Positionner le ballon a la tangente du joueur
|
||||||
|
this.ball.x = player.x + Math.cos(angle) * (player.radius + this.ball.radius);
|
||||||
|
this.ball.y = player.y + Math.sin(angle) * (player.radius + this.ball.radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier si la souris et a l'intérieur d'un cercle
|
||||||
|
private isInsideCircle(circle: Circle, x: number, y: number) {
|
||||||
|
const distance = Math.sqrt((x - circle.x) ** 2 + (y - circle.y) ** 2);
|
||||||
|
return distance <= circle.radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifier si la souris est a l'interieur d'un rectangle
|
||||||
|
private isInsideRectangle(rect: Rectangle, x: number, y: number) {
|
||||||
|
return x >= rect.x && x <= rect.x + rect.width &&
|
||||||
|
y >= rect.y && y <= rect.y + rect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Réinitialise le dessin sans effacer le terrain
|
// Réinitialise le dessin sans effacer le terrain
|
||||||
@@ -112,7 +378,7 @@ export class FootballFieldComponent {
|
|||||||
this.selectedColor = color;
|
this.selectedColor = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commence à dessiner quand la souris est enfoncée
|
// Commence a dessiner quand la souris est enfoncée
|
||||||
startDrawing(event: MouseEvent) {
|
startDrawing(event: MouseEvent) {
|
||||||
this.drawing = true;
|
this.drawing = true;
|
||||||
const { x, y } = this.getMousePos(event);
|
const { x, y } = this.getMousePos(event);
|
||||||
@@ -122,21 +388,6 @@ export class FootballFieldComponent {
|
|||||||
this.lastY = y;
|
this.lastY = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Dessine en suivant la souris
|
|
||||||
// draw(event: MouseEvent) {
|
|
||||||
// if (!this.drawing) return;
|
|
||||||
//
|
|
||||||
// const { x, y } = this.getMousePos(event);
|
|
||||||
// this.ctx.strokeStyle = this.selectedColor; // Utilise la couleur selectionnée
|
|
||||||
// this.ctx.lineWidth = 2;
|
|
||||||
// this.ctx.beginPath();
|
|
||||||
// this.ctx.moveTo(this.lastX, this.lastY);
|
|
||||||
// this.ctx.lineTo(x, y);
|
|
||||||
// this.ctx.stroke();
|
|
||||||
//
|
|
||||||
// this.lastX = x;
|
|
||||||
// this.lastY = y;
|
|
||||||
// }
|
|
||||||
// Dessiner en fonction de la forme sélectionnée
|
// Dessiner en fonction de la forme sélectionnée
|
||||||
draw(event: MouseEvent) {
|
draw(event: MouseEvent) {
|
||||||
if (!this.drawing) return;
|
if (!this.drawing) return;
|
||||||
@@ -209,5 +460,6 @@ export class FootballFieldComponent {
|
|||||||
this.canvas.nativeElement.width,
|
this.canvas.nativeElement.width,
|
||||||
this.canvas.nativeElement.height);
|
this.canvas.nativeElement.height);
|
||||||
this.drawField(); // Redessine le terrain de football
|
this.drawField(); // Redessine le terrain de football
|
||||||
|
this.updatePlayers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "./dist/out-tsc",
|
"outDir": "./dist/out-tsc",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
|
"strictNullChecks": false,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
"noPropertyAccessFromIndexSignature": true,
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user