canvasframework 0.5.2 → 0.5.3
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/Drawer.js +15 -0
- package/features/Skeleton.js +128 -19
- package/index.js +1 -1
- package/package.json +1 -1
package/components/Drawer.js
CHANGED
|
@@ -45,12 +45,27 @@ class Drawer extends Component {
|
|
|
45
45
|
// IMPORTANT: Définir les callbacks
|
|
46
46
|
this.onPress = this.handlePress;
|
|
47
47
|
this.onMove = this.handleMove;
|
|
48
|
+
// ✅ Se mettre automatiquement au-dessus de tous les composants
|
|
49
|
+
this.bringToFront();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Met le drawer au-dessus de tous les composants
|
|
54
|
+
* @private
|
|
55
|
+
*/
|
|
56
|
+
bringToFront() {
|
|
57
|
+
const index = this.framework.components.indexOf(this);
|
|
58
|
+
if (index > -1) {
|
|
59
|
+
this.framework.components.splice(index, 1);
|
|
60
|
+
this.framework.components.push(this);
|
|
61
|
+
}
|
|
48
62
|
}
|
|
49
63
|
|
|
50
64
|
/**
|
|
51
65
|
* Ouvre le drawer
|
|
52
66
|
*/
|
|
53
67
|
open() {
|
|
68
|
+
this.bringToFront(); // ✅ Se remettre au-dessus à chaque ouverture
|
|
54
69
|
this.visible = true;
|
|
55
70
|
this.targetX = 0;
|
|
56
71
|
this.animate();
|
package/features/Skeleton.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Component from '../core/Component.js';
|
|
2
|
+
|
|
2
3
|
/**
|
|
3
4
|
* Composant Skeleton (placeholder animé pendant le chargement)
|
|
4
5
|
* @class
|
|
@@ -6,7 +7,7 @@ import Component from '../core/Component.js';
|
|
|
6
7
|
* @param {Framework} framework - Instance du framework
|
|
7
8
|
* @param {Object} [options={}] - Options de configuration
|
|
8
9
|
* @param {string} [options.type='text'] - Type de skeleton ('text', 'circle', 'rectangle')
|
|
9
|
-
* @param {number} [options.
|
|
10
|
+
* @param {number} [options.animationDuration=1.5] - Durée de l'animation en secondes
|
|
10
11
|
* @example
|
|
11
12
|
* const skeleton = new Skeleton(framework, {
|
|
12
13
|
* type: 'text',
|
|
@@ -21,11 +22,14 @@ class Skeleton extends Component {
|
|
|
21
22
|
constructor(framework, options = {}) {
|
|
22
23
|
super(framework, options);
|
|
23
24
|
/** @type {string} */
|
|
24
|
-
this.type = options.type || 'text';
|
|
25
|
+
this.type = options.type || 'text';
|
|
26
|
+
/** @type {number} */
|
|
27
|
+
this.animationDuration = (options.animationDuration || 1.5) * 1000; // en ms
|
|
25
28
|
/** @type {number} */
|
|
26
|
-
this.
|
|
29
|
+
this.startTime = Date.now();
|
|
27
30
|
/** @type {number} */
|
|
28
|
-
this.
|
|
31
|
+
this.borderRadius = options.borderRadius || 4;
|
|
32
|
+
|
|
29
33
|
this.startAnimation();
|
|
30
34
|
}
|
|
31
35
|
|
|
@@ -35,50 +39,155 @@ class Skeleton extends Component {
|
|
|
35
39
|
*/
|
|
36
40
|
startAnimation() {
|
|
37
41
|
const animate = () => {
|
|
38
|
-
if (!this.visible)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (this.animationProgress > Math.PI * 2) {
|
|
42
|
-
this.animationProgress = 0;
|
|
42
|
+
if (!this.visible) {
|
|
43
|
+
requestAnimationFrame(animate);
|
|
44
|
+
return;
|
|
43
45
|
}
|
|
44
|
-
|
|
45
46
|
requestAnimationFrame(animate);
|
|
46
47
|
};
|
|
47
48
|
animate();
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
/**
|
|
51
|
-
*
|
|
52
|
+
* Calcule la progression de l'animation (0 à 1)
|
|
53
|
+
* @private
|
|
54
|
+
* @returns {number}
|
|
55
|
+
*/
|
|
56
|
+
getAnimationProgress() {
|
|
57
|
+
const elapsed = Date.now() - this.startTime;
|
|
58
|
+
const progress = (elapsed % this.animationDuration) / this.animationDuration;
|
|
59
|
+
return progress;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Crée le gradient shimmer diagonal style Ionic/Material
|
|
64
|
+
* @private
|
|
65
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
66
|
+
* @param {number} x
|
|
67
|
+
* @param {number} y
|
|
68
|
+
* @param {number} width
|
|
69
|
+
* @param {number} height
|
|
70
|
+
* @returns {CanvasGradient}
|
|
71
|
+
*/
|
|
72
|
+
createShimmerGradient(ctx, x, y, width, height) {
|
|
73
|
+
const progress = this.getAnimationProgress();
|
|
74
|
+
|
|
75
|
+
// Calculer la diagonale pour l'effet
|
|
76
|
+
const diagonal = Math.sqrt(width * width + height * height);
|
|
77
|
+
|
|
78
|
+
// Position du gradient qui se déplace
|
|
79
|
+
const offset = diagonal * 2;
|
|
80
|
+
const position = -diagonal + (offset * progress);
|
|
81
|
+
|
|
82
|
+
// Angle à 45 degrés (de haut-gauche vers bas-droite)
|
|
83
|
+
const angle = Math.PI / 4;
|
|
84
|
+
const cos = Math.cos(angle);
|
|
85
|
+
const sin = Math.sin(angle);
|
|
86
|
+
|
|
87
|
+
const gradient = ctx.createLinearGradient(
|
|
88
|
+
x + position * cos,
|
|
89
|
+
y + position * sin,
|
|
90
|
+
x + (position + diagonal) * cos,
|
|
91
|
+
y + (position + diagonal) * sin
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
// Gradient blanc avec transparence (style Ionic/Material)
|
|
95
|
+
gradient.addColorStop(0, 'rgba(255, 255, 255, 0)');
|
|
96
|
+
gradient.addColorStop(0.5, 'rgba(255, 255, 255, 0.4)');
|
|
97
|
+
gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
|
|
98
|
+
|
|
99
|
+
return gradient;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Dessine un rectangle arrondi
|
|
104
|
+
* @private
|
|
105
|
+
*/
|
|
106
|
+
roundRect(ctx, x, y, width, height, radius) {
|
|
107
|
+
if (width < 2 * radius) radius = width / 2;
|
|
108
|
+
if (height < 2 * radius) radius = height / 2;
|
|
109
|
+
|
|
110
|
+
ctx.beginPath();
|
|
111
|
+
ctx.moveTo(x + radius, y);
|
|
112
|
+
ctx.arcTo(x + width, y, x + width, y + height, radius);
|
|
113
|
+
ctx.arcTo(x + width, y + height, x, y + height, radius);
|
|
114
|
+
ctx.arcTo(x, y + height, x, y, radius);
|
|
115
|
+
ctx.arcTo(x, y, x + width, y, radius);
|
|
116
|
+
ctx.closePath();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Dessine le skeleton avec l'effet shimmer Ionic/Material
|
|
52
121
|
* @param {CanvasRenderingContext2D} ctx - Contexte de dessin
|
|
53
122
|
*/
|
|
54
123
|
draw(ctx) {
|
|
55
124
|
ctx.save();
|
|
56
125
|
|
|
57
|
-
|
|
58
|
-
|
|
126
|
+
// Couleur de fond (gris clair Material)
|
|
127
|
+
const backgroundColor = '#e0e0e0';
|
|
59
128
|
|
|
60
129
|
switch(this.type) {
|
|
61
130
|
case 'circle':
|
|
131
|
+
// Dessiner le cercle de base
|
|
132
|
+
ctx.fillStyle = backgroundColor;
|
|
62
133
|
ctx.beginPath();
|
|
63
134
|
ctx.arc(this.x + this.width/2, this.y + this.height/2, this.width/2, 0, Math.PI * 2);
|
|
64
135
|
ctx.fill();
|
|
136
|
+
|
|
137
|
+
// Créer un clipping path pour le shimmer
|
|
138
|
+
ctx.beginPath();
|
|
139
|
+
ctx.arc(this.x + this.width/2, this.y + this.height/2, this.width/2, 0, Math.PI * 2);
|
|
140
|
+
ctx.clip();
|
|
141
|
+
|
|
142
|
+
// Appliquer le shimmer
|
|
143
|
+
ctx.fillStyle = this.createShimmerGradient(ctx, this.x, this.y, this.width, this.height);
|
|
144
|
+
ctx.fillRect(this.x, this.y, this.width, this.height);
|
|
65
145
|
break;
|
|
146
|
+
|
|
66
147
|
case 'text':
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
const
|
|
148
|
+
const lineHeight = 16;
|
|
149
|
+
const lineSpacing = 10;
|
|
150
|
+
const totalLineHeight = lineHeight + lineSpacing;
|
|
151
|
+
const lines = Math.floor(this.height / totalLineHeight);
|
|
70
152
|
|
|
71
153
|
for (let i = 0; i < lines; i++) {
|
|
72
154
|
const lineWidth = i === lines - 1 ? this.width * 0.6 : this.width;
|
|
73
|
-
|
|
155
|
+
const lineY = this.y + i * totalLineHeight;
|
|
156
|
+
|
|
157
|
+
// Fond de la ligne
|
|
158
|
+
ctx.fillStyle = backgroundColor;
|
|
159
|
+
this.roundRect(ctx, this.x, lineY, lineWidth, lineHeight, this.borderRadius);
|
|
160
|
+
ctx.fill();
|
|
161
|
+
|
|
162
|
+
// Shimmer sur la ligne
|
|
163
|
+
ctx.save();
|
|
164
|
+
this.roundRect(ctx, this.x, lineY, lineWidth, lineHeight, this.borderRadius);
|
|
165
|
+
ctx.clip();
|
|
166
|
+
|
|
167
|
+
ctx.fillStyle = this.createShimmerGradient(ctx, this.x, lineY, lineWidth, lineHeight);
|
|
168
|
+
ctx.fillRect(this.x - 100, lineY - 100, lineWidth + 200, lineHeight + 200);
|
|
169
|
+
ctx.restore();
|
|
74
170
|
}
|
|
75
171
|
break;
|
|
172
|
+
|
|
76
173
|
default:
|
|
77
|
-
|
|
174
|
+
// Rectangle de base
|
|
175
|
+
ctx.fillStyle = backgroundColor;
|
|
176
|
+
this.roundRect(ctx, this.x, this.y, this.width, this.height, this.borderRadius);
|
|
177
|
+
ctx.fill();
|
|
178
|
+
|
|
179
|
+
// Shimmer
|
|
180
|
+
ctx.save();
|
|
181
|
+
this.roundRect(ctx, this.x, this.y, this.width, this.height, this.borderRadius);
|
|
182
|
+
ctx.clip();
|
|
183
|
+
|
|
184
|
+
ctx.fillStyle = this.createShimmerGradient(ctx, this.x, this.y, this.width, this.height);
|
|
185
|
+
ctx.fillRect(this.x - 100, this.y - 100, this.width + 200, this.height + 200);
|
|
186
|
+
ctx.restore();
|
|
78
187
|
}
|
|
79
188
|
|
|
80
189
|
ctx.restore();
|
|
81
190
|
}
|
|
82
191
|
}
|
|
83
192
|
|
|
84
|
-
export default Skeleton;
|
|
193
|
+
export default Skeleton;
|
package/index.js
CHANGED