canvasframework 0.5.23 → 0.5.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/Card.js +151 -123
- package/package.json +1 -1
package/components/Card.js
CHANGED
|
@@ -1,150 +1,167 @@
|
|
|
1
1
|
import Component from '../core/Component.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Container avec système de layout et effet d'élévation
|
|
4
4
|
* @class
|
|
5
5
|
* @extends Component
|
|
6
|
-
* @property {Component[]} children - Enfants
|
|
6
|
+
* @property {Component[]} children - Enfants
|
|
7
7
|
* @property {number} padding - Padding interne
|
|
8
|
+
* @property {number} gap - Espacement entre enfants
|
|
9
|
+
* @property {string} direction - Direction ('column' ou 'row')
|
|
10
|
+
* @property {string} align - Alignement ('start', 'center', 'end')
|
|
8
11
|
* @property {string} bgColor - Couleur de fond
|
|
9
|
-
* @property {number} elevation - Élévation (ombre)
|
|
10
12
|
* @property {number} borderRadius - Rayon des coins
|
|
11
|
-
* @property {
|
|
12
|
-
* @property {boolean} clickableChildren - Active les clics sur les enfants
|
|
13
|
+
* @property {number} elevation - Niveau d'élévation (ombres)
|
|
13
14
|
*/
|
|
14
15
|
class Card extends Component {
|
|
15
16
|
/**
|
|
16
17
|
* Crée une instance de Card
|
|
17
18
|
* @param {CanvasFramework} framework - Framework parent
|
|
18
19
|
* @param {Object} [options={}] - Options de configuration
|
|
19
|
-
* @param {number} [options.padding=
|
|
20
|
-
* @param {
|
|
21
|
-
* @param {
|
|
22
|
-
* @param {
|
|
23
|
-
* @param {
|
|
24
|
-
* @param {
|
|
20
|
+
* @param {number} [options.padding=0] - Padding interne
|
|
21
|
+
* @param {number} [options.gap=0] - Espacement entre enfants
|
|
22
|
+
* @param {string} [options.direction='column'] - Direction
|
|
23
|
+
* @param {string} [options.align='start'] - Alignement
|
|
24
|
+
* @param {string} [options.bgColor='transparent'] - Couleur de fond
|
|
25
|
+
* @param {number} [options.borderRadius=0] - Rayon des coins
|
|
26
|
+
* @param {number} [options.elevation=0] - Niveau d'élévation (0-5)
|
|
25
27
|
*/
|
|
26
28
|
constructor(framework, options = {}) {
|
|
27
29
|
super(framework, options);
|
|
28
30
|
this.children = [];
|
|
29
|
-
this.padding = options.padding ||
|
|
30
|
-
this.
|
|
31
|
-
this.
|
|
32
|
-
this.
|
|
33
|
-
this.
|
|
34
|
-
this.
|
|
31
|
+
this.padding = options.padding || 0;
|
|
32
|
+
this.gap = options.gap || 0;
|
|
33
|
+
this.direction = options.direction || 'column';
|
|
34
|
+
this.align = options.align || 'start';
|
|
35
|
+
this.bgColor = options.bgColor || 'transparent';
|
|
36
|
+
this.borderRadius = options.borderRadius || 0;
|
|
37
|
+
this.elevation = options.elevation || 0; // Nouvelle propriété
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
/**
|
|
38
|
-
* Ajoute un enfant
|
|
41
|
+
* Ajoute un enfant
|
|
39
42
|
* @param {Component} child - Composant enfant
|
|
40
43
|
* @returns {Component} L'enfant ajouté
|
|
41
44
|
*/
|
|
42
45
|
add(child) {
|
|
43
|
-
// Ajuster les coordonnées de l'enfant pour qu'elles soient relatives à la Card
|
|
44
|
-
child.x = child.x || 0;
|
|
45
|
-
child.y = child.y || 0;
|
|
46
46
|
this.children.push(child);
|
|
47
|
+
this.layout();
|
|
48
|
+
return child;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Organise les enfants selon le layout
|
|
53
|
+
* @private
|
|
54
|
+
*/
|
|
55
|
+
layout() {
|
|
56
|
+
let currentX = this.x + this.padding;
|
|
57
|
+
let currentY = this.y + this.padding;
|
|
47
58
|
|
|
48
|
-
|
|
49
|
-
|
|
59
|
+
for (let child of this.children) {
|
|
60
|
+
if (this.direction === 'column') {
|
|
61
|
+
child.x = currentX;
|
|
62
|
+
child.y = currentY;
|
|
63
|
+
if (this.align === 'center') {
|
|
64
|
+
child.x = this.x + (this.width - child.width) / 2;
|
|
65
|
+
} else if (this.align === 'end') {
|
|
66
|
+
child.x = this.x + this.width - child.width - this.padding;
|
|
67
|
+
}
|
|
68
|
+
currentY += child.height + this.gap;
|
|
69
|
+
} else {
|
|
70
|
+
child.x = currentX;
|
|
71
|
+
child.y = currentY;
|
|
72
|
+
if (this.align === 'center') {
|
|
73
|
+
child.y = this.y + (this.height - child.height) / 2;
|
|
74
|
+
} else if (this.align === 'end') {
|
|
75
|
+
child.y = this.y + this.height - child.height - this.padding;
|
|
76
|
+
}
|
|
77
|
+
currentX += child.width + this.gap;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Génère les paramètres d'ombre selon le niveau d'élévation
|
|
84
|
+
* @param {number} elevation - Niveau d'élévation (0-5)
|
|
85
|
+
* @returns {Object} Configuration de l'ombre
|
|
86
|
+
* @private
|
|
87
|
+
*/
|
|
88
|
+
getShadowConfig(elevation) {
|
|
89
|
+
const shadows = [
|
|
90
|
+
{ blur: 0, offsetY: 0, color: 'transparent', spread: 0 }, // 0 - pas d'ombre
|
|
91
|
+
{ blur: 2, offsetY: 1, color: 'rgba(0,0,0,0.12)', spread: 0 }, // 1 - léger
|
|
92
|
+
{ blur: 3, offsetY: 1, color: 'rgba(0,0,0,0.14)', spread: 0 }, // 2 - léger
|
|
93
|
+
{ blur: 4, offsetY: 2, color: 'rgba(0,0,0,0.16)', spread: 0 }, // 3 - moyen
|
|
94
|
+
{ blur: 6, offsetY: 3, color: 'rgba(0,0,0,0.18)', spread: 0 }, // 4 - moyen
|
|
95
|
+
{ blur: 8, offsetY: 4, color: 'rgba(0,0,0,0.20)', spread: 0 }, // 5 - fort
|
|
96
|
+
];
|
|
50
97
|
|
|
51
|
-
return
|
|
98
|
+
return shadows[Math.min(elevation, shadows.length - 1)];
|
|
52
99
|
}
|
|
53
100
|
|
|
54
101
|
/**
|
|
55
|
-
* Dessine
|
|
102
|
+
* Dessine l'effet d'ombre selon l'élévation
|
|
56
103
|
* @param {CanvasRenderingContext2D} ctx - Contexte de dessin
|
|
104
|
+
* @private
|
|
57
105
|
*/
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Children - dessinés relativement à la Card
|
|
88
|
-
for (let child of this.children) {
|
|
89
|
-
if (child.visible) {
|
|
90
|
-
// *** FIX : Utiliser ctx.translate au lieu de modifier child.x/y ***
|
|
91
|
-
ctx.save();
|
|
92
|
-
ctx.translate(this.x + this.padding, this.y + this.padding);
|
|
93
|
-
|
|
94
|
-
// Dessiner l'enfant (ses coordonnées sont déjà relatives)
|
|
95
|
-
child.draw(ctx);
|
|
96
|
-
|
|
97
|
-
ctx.restore();
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
ctx.restore();
|
|
102
|
-
}
|
|
106
|
+
drawShadow(ctx) {
|
|
107
|
+
if (this.elevation <= 0) return;
|
|
108
|
+
|
|
109
|
+
const shadow = this.getShadowConfig(this.elevation);
|
|
110
|
+
|
|
111
|
+
// Sauvegarder l'état du contexte
|
|
112
|
+
ctx.save();
|
|
113
|
+
|
|
114
|
+
// Configurer l'ombre
|
|
115
|
+
ctx.shadowColor = shadow.color;
|
|
116
|
+
ctx.shadowBlur = shadow.blur;
|
|
117
|
+
ctx.shadowOffsetX = 0;
|
|
118
|
+
ctx.shadowOffsetY = shadow.offsetY;
|
|
119
|
+
|
|
120
|
+
// Dessiner un rectangle pour l'ombre
|
|
121
|
+
if (this.borderRadius > 0) {
|
|
122
|
+
ctx.beginPath();
|
|
123
|
+
this.roundRect(ctx, this.x, this.y + shadow.offsetY, this.width, this.height, this.borderRadius);
|
|
124
|
+
ctx.fillStyle = this.bgColor === 'transparent' ? 'white' : this.bgColor;
|
|
125
|
+
ctx.fill();
|
|
126
|
+
} else {
|
|
127
|
+
ctx.fillStyle = this.bgColor === 'transparent' ? 'white' : this.bgColor;
|
|
128
|
+
ctx.fillRect(this.x, this.y + shadow.offsetY, this.width, this.height);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
ctx.restore();
|
|
132
|
+
}
|
|
103
133
|
|
|
104
134
|
/**
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
// Déclencher onClick ou onPress
|
|
136
|
-
if (child.onClick) {
|
|
137
|
-
child.onClick();
|
|
138
|
-
return true;
|
|
139
|
-
} else if (child.onPress) {
|
|
140
|
-
child.onPress(x, adjustedY);
|
|
141
|
-
return true;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
135
|
+
* Dessine la carte et ses enfants
|
|
136
|
+
* @param {CanvasRenderingContext2D} ctx - Contexte de dessin
|
|
137
|
+
*/
|
|
138
|
+
draw(ctx) {
|
|
139
|
+
ctx.save();
|
|
140
|
+
|
|
141
|
+
// Dessiner l'ombre si elevation > 0
|
|
142
|
+
if (this.elevation > 0) {
|
|
143
|
+
this.drawShadow(ctx);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Dessiner le fond de la carte
|
|
147
|
+
if (this.bgColor !== 'transparent') {
|
|
148
|
+
ctx.fillStyle = this.bgColor;
|
|
149
|
+
if (this.borderRadius > 0) {
|
|
150
|
+
ctx.beginPath();
|
|
151
|
+
this.roundRect(ctx, this.x, this.y, this.width, this.height, this.borderRadius);
|
|
152
|
+
ctx.fill();
|
|
153
|
+
} else {
|
|
154
|
+
ctx.fillRect(this.x, this.y, this.width, this.height);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Dessiner les enfants
|
|
159
|
+
for (let child of this.children) {
|
|
160
|
+
if (child.visible) child.draw(ctx);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
ctx.restore();
|
|
164
|
+
}
|
|
148
165
|
|
|
149
166
|
/**
|
|
150
167
|
* Dessine un rectangle avec coins arrondis
|
|
@@ -157,7 +174,6 @@ class Card extends Component {
|
|
|
157
174
|
* @private
|
|
158
175
|
*/
|
|
159
176
|
roundRect(ctx, x, y, width, height, radius) {
|
|
160
|
-
ctx.beginPath();
|
|
161
177
|
ctx.moveTo(x + radius, y);
|
|
162
178
|
ctx.lineTo(x + width - radius, y);
|
|
163
179
|
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
|
|
@@ -167,14 +183,13 @@ class Card extends Component {
|
|
|
167
183
|
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
|
|
168
184
|
ctx.lineTo(x, y + radius);
|
|
169
185
|
ctx.quadraticCurveTo(x, y, x + radius, y);
|
|
170
|
-
ctx.closePath();
|
|
171
186
|
}
|
|
172
|
-
|
|
187
|
+
|
|
173
188
|
/**
|
|
174
189
|
* Vérifie si un point est dans les limites
|
|
175
190
|
* @param {number} x - Coordonnée X
|
|
176
191
|
* @param {number} y - Coordonnée Y
|
|
177
|
-
* @returns {boolean} True si le point est dans la
|
|
192
|
+
* @returns {boolean} True si le point est dans la vue
|
|
178
193
|
*/
|
|
179
194
|
isPointInside(x, y) {
|
|
180
195
|
return x >= this.x &&
|
|
@@ -182,14 +197,27 @@ class Card extends Component {
|
|
|
182
197
|
y >= this.y &&
|
|
183
198
|
y <= this.y + this.height;
|
|
184
199
|
}
|
|
185
|
-
|
|
200
|
+
|
|
186
201
|
/**
|
|
187
|
-
*
|
|
188
|
-
* @
|
|
202
|
+
* Définit le niveau d'élévation
|
|
203
|
+
* @param {number} elevation - Nouveau niveau d'élévation (0-5)
|
|
204
|
+
*/
|
|
205
|
+
setElevation(elevation) {
|
|
206
|
+
this.elevation = Math.max(0, Math.min(elevation, 5));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Augmente le niveau d'élévation
|
|
211
|
+
*/
|
|
212
|
+
raise() {
|
|
213
|
+
this.setElevation(this.elevation + 1);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Réduit le niveau d'élévation
|
|
189
218
|
*/
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
// Cette logique est gérée dans le CanvasFramework modifié ci-dessous
|
|
219
|
+
lower() {
|
|
220
|
+
this.setElevation(this.elevation - 1);
|
|
193
221
|
}
|
|
194
222
|
}
|
|
195
223
|
|