canvasframework 0.5.10 → 0.5.12
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/Camera.js +20 -0
- package/components/FloatedCamera.js +21 -1
- package/core/CanvasFramework.js +170 -178
- package/package.json +1 -1
package/components/Camera.js
CHANGED
|
@@ -34,6 +34,25 @@ class Camera extends Component {
|
|
|
34
34
|
|
|
35
35
|
this.isStarting = false;
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
static cleanupAllCameras() {
|
|
39
|
+
const allVideos = document.querySelectorAll('video');
|
|
40
|
+
allVideos.forEach(video => {
|
|
41
|
+
// Arrêter les streams
|
|
42
|
+
if (video.srcObject) {
|
|
43
|
+
const stream = video.srcObject;
|
|
44
|
+
if (stream && stream.getTracks) {
|
|
45
|
+
stream.getTracks().forEach(track => track.stop());
|
|
46
|
+
}
|
|
47
|
+
video.srcObject = null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Supprimer du DOM
|
|
51
|
+
if (video.parentNode) {
|
|
52
|
+
video.parentNode.removeChild(video);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
37
56
|
|
|
38
57
|
async _mount() {
|
|
39
58
|
super._mount?.();
|
|
@@ -120,6 +139,7 @@ class Camera extends Component {
|
|
|
120
139
|
handleMouseUp(e) {}
|
|
121
140
|
|
|
122
141
|
async startCamera() {
|
|
142
|
+
Camera.cleanupAllCameras();
|
|
123
143
|
if (this.stream) return;
|
|
124
144
|
|
|
125
145
|
try {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Component from '../core/Component.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Composant
|
|
4
|
+
* Composant Camera autonome avec gestion directe des clics/touches
|
|
5
5
|
* Modes : contain (tout visible + bandes), cover (remplit + crop), fit (centre sans crop)
|
|
6
6
|
*/
|
|
7
7
|
class FloatedCamera extends Component {
|
|
@@ -34,6 +34,25 @@ class FloatedCamera extends Component {
|
|
|
34
34
|
|
|
35
35
|
this.isStarting = false;
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
static cleanupAllCameras() {
|
|
39
|
+
const allVideos = document.querySelectorAll('video');
|
|
40
|
+
allVideos.forEach(video => {
|
|
41
|
+
// Arrêter les streams
|
|
42
|
+
if (video.srcObject) {
|
|
43
|
+
const stream = video.srcObject;
|
|
44
|
+
if (stream && stream.getTracks) {
|
|
45
|
+
stream.getTracks().forEach(track => track.stop());
|
|
46
|
+
}
|
|
47
|
+
video.srcObject = null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Supprimer du DOM
|
|
51
|
+
if (video.parentNode) {
|
|
52
|
+
video.parentNode.removeChild(video);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
37
56
|
|
|
38
57
|
async _mount() {
|
|
39
58
|
super._mount?.();
|
|
@@ -120,6 +139,7 @@ class FloatedCamera extends Component {
|
|
|
120
139
|
handleMouseUp(e) {}
|
|
121
140
|
|
|
122
141
|
async startCamera() {
|
|
142
|
+
FloatedCamera.cleanupAllCameras();
|
|
123
143
|
if (this.stream) return;
|
|
124
144
|
|
|
125
145
|
try {
|
package/core/CanvasFramework.js
CHANGED
|
@@ -1781,6 +1781,7 @@ class CanvasFramework {
|
|
|
1781
1781
|
* @private
|
|
1782
1782
|
*/
|
|
1783
1783
|
async navigateTo(path, options = {}) {
|
|
1784
|
+
|
|
1784
1785
|
const {
|
|
1785
1786
|
replace = false,
|
|
1786
1787
|
animate = true,
|
|
@@ -1803,7 +1804,7 @@ class CanvasFramework {
|
|
|
1803
1804
|
} = match;
|
|
1804
1805
|
|
|
1805
1806
|
// ===== LIFECYCLE: AVANT DE QUITTER L'ANCIENNE ROUTE =====
|
|
1806
|
-
|
|
1807
|
+
|
|
1807
1808
|
// Hook beforeLeave de la route actuelle (peut bloquer la navigation)
|
|
1808
1809
|
const currentRouteData = this.routes.get(this.currentRoute);
|
|
1809
1810
|
if (currentRouteData?.beforeLeave) {
|
|
@@ -1930,6 +1931,17 @@ class CanvasFramework {
|
|
|
1930
1931
|
|
|
1931
1932
|
// ✅ OPTIONNEL : Marquer les composants comme "dirty" pour forcer le rendu
|
|
1932
1933
|
this._maxScrollDirty = true;
|
|
1934
|
+
|
|
1935
|
+
this.components.forEach(comp => {
|
|
1936
|
+
// Vérifier si c'est un composant caméra
|
|
1937
|
+
if (comp.constructor.name === 'FloatedCamera' || comp.constructor.name === 'Camera') {
|
|
1938
|
+
// Arrêter le stream vidéo
|
|
1939
|
+
if (comp.stopCamera && typeof comp.stopCamera === 'function') {
|
|
1940
|
+
comp.stopCamera();
|
|
1941
|
+
console.log(`🎥 Caméra ${comp.constructor.name} arrêtée avant navigation`);
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
});
|
|
1933
1945
|
}
|
|
1934
1946
|
|
|
1935
1947
|
/**
|
|
@@ -2662,65 +2674,38 @@ class CanvasFramework {
|
|
|
2662
2674
|
|
|
2663
2675
|
startRenderLoop() {
|
|
2664
2676
|
let lastScrollOffset = this.scrollOffset;
|
|
2665
|
-
let lastRenderMode = 'full';
|
|
2666
|
-
let lastFrameTime = performance.now();
|
|
2667
2677
|
|
|
2668
|
-
const render = (
|
|
2669
|
-
// Calculer le delta time
|
|
2670
|
-
const deltaTime = currentTime - lastFrameTime;
|
|
2671
|
-
lastFrameTime = currentTime;
|
|
2672
|
-
|
|
2678
|
+
const render = () => {
|
|
2673
2679
|
if (!this._splashFinished) {
|
|
2674
2680
|
requestAnimationFrame(render);
|
|
2675
2681
|
return;
|
|
2676
2682
|
}
|
|
2677
2683
|
|
|
2678
|
-
//
|
|
2684
|
+
// TOUJOURS effacer l'écran en premier
|
|
2685
|
+
this.ctx.fillStyle = this.backgroundColor || '#ffffff';
|
|
2686
|
+
this.ctx.fillRect(0, 0, this.width, this.height);
|
|
2687
|
+
|
|
2688
|
+
// Si une transition est en cours
|
|
2679
2689
|
if (this.transitionState.isTransitioning) {
|
|
2680
|
-
|
|
2690
|
+
// Mettre à jour la progression
|
|
2691
|
+
const elapsed = Date.now() - this.transitionState.startTime;
|
|
2692
|
+
this.transitionState.progress = Math.min(elapsed / this.transitionState.duration, 1);
|
|
2681
2693
|
|
|
2682
|
-
//
|
|
2694
|
+
// Rendu spécial pour la transition
|
|
2695
|
+
this.renderSimpleTransition();
|
|
2696
|
+
|
|
2697
|
+
// Si la transition est terminée
|
|
2683
2698
|
if (this.transitionState.progress >= 1) {
|
|
2684
2699
|
this.transitionState.isTransitioning = false;
|
|
2685
2700
|
this.transitionState.oldComponents = [];
|
|
2686
2701
|
}
|
|
2687
|
-
}
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
const scrollChanged = Math.abs(this.scrollOffset - lastScrollOffset) > 0.1;
|
|
2691
|
-
lastScrollOffset = this.scrollOffset;
|
|
2692
|
-
|
|
2693
|
-
// 3. Décider du mode de rendu
|
|
2694
|
-
let renderMode = 'full';
|
|
2695
|
-
|
|
2696
|
-
// Conditions pour utiliser le rendu optimisé (dirty components)
|
|
2697
|
-
if (this.optimizationEnabled &&
|
|
2698
|
-
!this.transitionState.isTransitioning && // ← Pas pendant les transitions
|
|
2699
|
-
this.dirtyComponents.size > 0 &&
|
|
2700
|
-
!this.isDragging &&
|
|
2701
|
-
Math.abs(this.scrollVelocity) < 0.5 &&
|
|
2702
|
-
!scrollChanged &&
|
|
2703
|
-
this.dirtyComponents.size < 3) {
|
|
2704
|
-
renderMode = 'dirty';
|
|
2705
|
-
}
|
|
2706
|
-
|
|
2707
|
-
// 4. Exécuter le rendu
|
|
2708
|
-
if (this.transitionState.isTransitioning) {
|
|
2709
|
-
// Pendant les transitions, toujours utiliser un rendu complet spécial
|
|
2710
|
-
this.renderTransition();
|
|
2711
|
-
} else if (renderMode === 'full' || lastRenderMode !== renderMode) {
|
|
2712
|
-
// Rendu complet normal
|
|
2713
|
-
this.ctx.fillStyle = this.backgroundColor || '#ffffff';
|
|
2714
|
-
this.ctx.fillRect(0, 0, this.width, this.height);
|
|
2702
|
+
}
|
|
2703
|
+
// Sinon, rendu normal
|
|
2704
|
+
else {
|
|
2715
2705
|
this.renderFull();
|
|
2716
|
-
} else {
|
|
2717
|
-
// Rendu optimisé (seulement les composants sales)
|
|
2718
|
-
this._renderDirtyComponents();
|
|
2719
2706
|
}
|
|
2720
2707
|
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
// 5. Calculer et afficher le FPS
|
|
2708
|
+
// Calcul FPS (optionnel)
|
|
2724
2709
|
this._frames++;
|
|
2725
2710
|
const now = performance.now();
|
|
2726
2711
|
const elapsed = now - this._lastFpsTime;
|
|
@@ -2731,7 +2716,6 @@ class CanvasFramework {
|
|
|
2731
2716
|
this._lastFpsTime = now;
|
|
2732
2717
|
}
|
|
2733
2718
|
|
|
2734
|
-
// Afficher le FPS si activé
|
|
2735
2719
|
if (this.showFps) {
|
|
2736
2720
|
this.ctx.save();
|
|
2737
2721
|
this.ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
|
|
@@ -2744,158 +2728,170 @@ class CanvasFramework {
|
|
|
2744
2728
|
this.ctx.restore();
|
|
2745
2729
|
}
|
|
2746
2730
|
|
|
2747
|
-
//
|
|
2748
|
-
if (this.debbug) {
|
|
2749
|
-
this.drawOverflowIndicators();
|
|
2750
|
-
}
|
|
2751
|
-
|
|
2752
|
-
// Marquer le premier rendu
|
|
2753
|
-
if (!this._firstRenderDone) {
|
|
2754
|
-
this._markFirstRender();
|
|
2755
|
-
}
|
|
2756
|
-
|
|
2757
|
-
// Mettre à jour l'inertie du scroll si nécessaire
|
|
2731
|
+
// Mettre à jour l'inertie du scroll
|
|
2758
2732
|
if (Math.abs(this.scrollVelocity) > 0.1 && !this.isDragging) {
|
|
2759
2733
|
this.scrollWorker.postMessage({ type: 'UPDATE_INERTIA' });
|
|
2760
2734
|
}
|
|
2761
2735
|
|
|
2762
|
-
// Nettoyer les composants sales après le rendu
|
|
2763
|
-
if (renderMode === 'full') {
|
|
2764
|
-
this.dirtyComponents.clear();
|
|
2765
|
-
}
|
|
2766
|
-
|
|
2767
2736
|
requestAnimationFrame(render);
|
|
2768
2737
|
};
|
|
2769
2738
|
|
|
2770
|
-
render(
|
|
2739
|
+
render();
|
|
2771
2740
|
}
|
|
2772
|
-
|
|
2773
|
-
|
|
2741
|
+
|
|
2774
2742
|
/**
|
|
2775
|
-
* Rendu
|
|
2776
|
-
* @private
|
|
2743
|
+
* Rendu ultra simple pour la transition slide
|
|
2777
2744
|
*/
|
|
2778
|
-
|
|
2779
|
-
const
|
|
2745
|
+
renderSimpleTransition() {
|
|
2746
|
+
const { progress, type, direction, oldComponents, newComponents } = this.transitionState;
|
|
2780
2747
|
|
|
2781
|
-
//
|
|
2782
|
-
|
|
2783
|
-
ctx.fillRect(0, 0, this.width, this.height);
|
|
2748
|
+
// Easing pour une animation plus fluide
|
|
2749
|
+
const eased = this.easeInOutCubic(progress);
|
|
2784
2750
|
|
|
2785
|
-
// Dessiner l'animation de transition
|
|
2786
|
-
const progress = this.transitionState.progress;
|
|
2787
|
-
const { type, direction, oldComponents, newComponents } = this.transitionState;
|
|
2788
2751
|
const directionMultiplier = direction === 'forward' ? 1 : -1;
|
|
2789
2752
|
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
}
|
|
2814
|
-
}
|
|
2815
|
-
}
|
|
2816
|
-
ctx.restore();
|
|
2817
|
-
|
|
2818
|
-
// 2. Nouvelle vue qui entre
|
|
2819
|
-
ctx.save();
|
|
2820
|
-
ctx.translate(this.width * (1 - eased) * directionMultiplier, 0);
|
|
2821
|
-
|
|
2822
|
-
for (let comp of newComponents) {
|
|
2823
|
-
if (comp && comp.visible) {
|
|
2824
|
-
const isFixed = this.isFixedComponent(comp);
|
|
2825
|
-
|
|
2826
|
-
if (isFixed) {
|
|
2827
|
-
comp.draw(ctx);
|
|
2828
|
-
} else {
|
|
2829
|
-
ctx.save();
|
|
2830
|
-
ctx.translate(0, this.scrollOffset);
|
|
2831
|
-
comp.draw(ctx);
|
|
2832
|
-
ctx.restore();
|
|
2833
|
-
}
|
|
2753
|
+
if (type === 'slide') {
|
|
2754
|
+
// ✅ AMÉLIORATION 1 : Dessiner l'ANCIENNE vue qui sort
|
|
2755
|
+
this.ctx.save();
|
|
2756
|
+
|
|
2757
|
+
// L'ancienne vue se déplace vers la gauche/droite
|
|
2758
|
+
const oldOffset = -this.width * eased * directionMultiplier;
|
|
2759
|
+
this.ctx.translate(oldOffset, 0);
|
|
2760
|
+
|
|
2761
|
+
// Légère transparence pour donner de la profondeur
|
|
2762
|
+
this.ctx.globalAlpha = 1 - (eased * 0.3);
|
|
2763
|
+
|
|
2764
|
+
// Dessiner les anciens composants
|
|
2765
|
+
for (let comp of oldComponents) {
|
|
2766
|
+
if (comp && comp.visible) {
|
|
2767
|
+
const isFixed = this.isFixedComponent(comp);
|
|
2768
|
+
|
|
2769
|
+
if (isFixed) {
|
|
2770
|
+
comp.draw(this.ctx);
|
|
2771
|
+
} else {
|
|
2772
|
+
this.ctx.save();
|
|
2773
|
+
this.ctx.translate(0, 0); // Pas de scroll pendant la transition
|
|
2774
|
+
comp.draw(this.ctx);
|
|
2775
|
+
this.ctx.restore();
|
|
2834
2776
|
}
|
|
2835
2777
|
}
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2778
|
+
}
|
|
2779
|
+
|
|
2780
|
+
this.ctx.restore();
|
|
2781
|
+
|
|
2782
|
+
// ✅ AMÉLIORATION 2 : Dessiner la NOUVELLE vue qui entre
|
|
2783
|
+
this.ctx.save();
|
|
2784
|
+
|
|
2785
|
+
// La nouvelle vue arrive de la droite/gauche
|
|
2786
|
+
const newOffset = this.width * (1 - eased) * directionMultiplier;
|
|
2787
|
+
this.ctx.translate(newOffset, 0);
|
|
2788
|
+
|
|
2789
|
+
// Dessiner les nouveaux composants
|
|
2790
|
+
for (let comp of newComponents) {
|
|
2791
|
+
if (comp && comp.visible) {
|
|
2792
|
+
const isFixed = this.isFixedComponent(comp);
|
|
2793
|
+
|
|
2794
|
+
if (isFixed) {
|
|
2795
|
+
comp.draw(this.ctx);
|
|
2796
|
+
} else {
|
|
2797
|
+
this.ctx.save();
|
|
2798
|
+
this.ctx.translate(0, 0); // Pas de scroll pendant la transition
|
|
2799
|
+
comp.draw(this.ctx);
|
|
2800
|
+
this.ctx.restore();
|
|
2855
2801
|
}
|
|
2856
2802
|
}
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2803
|
+
}
|
|
2804
|
+
|
|
2805
|
+
this.ctx.restore();
|
|
2806
|
+
}
|
|
2807
|
+
else if (type === 'fade') {
|
|
2808
|
+
// Ancienne vue qui fade out
|
|
2809
|
+
this.ctx.save();
|
|
2810
|
+
this.ctx.globalAlpha = 1 - eased;
|
|
2811
|
+
|
|
2812
|
+
for (let comp of oldComponents) {
|
|
2813
|
+
if (comp && comp.visible) {
|
|
2814
|
+
const isFixed = this.isFixedComponent(comp);
|
|
2815
|
+
if (isFixed) {
|
|
2816
|
+
comp.draw(this.ctx);
|
|
2817
|
+
} else {
|
|
2818
|
+
this.ctx.save();
|
|
2819
|
+
this.ctx.translate(0, 0);
|
|
2820
|
+
comp.draw(this.ctx);
|
|
2821
|
+
this.ctx.restore();
|
|
2874
2822
|
}
|
|
2875
2823
|
}
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2824
|
+
}
|
|
2825
|
+
|
|
2826
|
+
this.ctx.restore();
|
|
2827
|
+
|
|
2828
|
+
// Nouvelle vue qui fade in
|
|
2829
|
+
this.ctx.save();
|
|
2830
|
+
this.ctx.globalAlpha = eased;
|
|
2831
|
+
|
|
2832
|
+
for (let comp of newComponents) {
|
|
2833
|
+
if (comp && comp.visible) {
|
|
2834
|
+
const isFixed = this.isFixedComponent(comp);
|
|
2835
|
+
if (isFixed) {
|
|
2836
|
+
comp.draw(this.ctx);
|
|
2837
|
+
} else {
|
|
2838
|
+
this.ctx.save();
|
|
2839
|
+
this.ctx.translate(0, 0);
|
|
2840
|
+
comp.draw(this.ctx);
|
|
2841
|
+
this.ctx.restore();
|
|
2893
2842
|
}
|
|
2894
2843
|
}
|
|
2895
|
-
|
|
2844
|
+
}
|
|
2845
|
+
|
|
2846
|
+
this.ctx.restore();
|
|
2847
|
+
}
|
|
2848
|
+
else {
|
|
2849
|
+
this.renderFull();
|
|
2896
2850
|
}
|
|
2897
2851
|
}
|
|
2898
2852
|
|
|
2853
|
+
/**
|
|
2854
|
+
* Rendu normal (sans transition)
|
|
2855
|
+
*/
|
|
2856
|
+
renderFull() {
|
|
2857
|
+
this.ctx.save();
|
|
2858
|
+
|
|
2859
|
+
// Séparer les composants fixes et scrollables
|
|
2860
|
+
const scrollableComponents = [];
|
|
2861
|
+
const fixedComponents = [];
|
|
2862
|
+
|
|
2863
|
+
for (let comp of this.components) {
|
|
2864
|
+
if (this.isFixedComponent(comp)) {
|
|
2865
|
+
fixedComponents.push(comp);
|
|
2866
|
+
} else {
|
|
2867
|
+
scrollableComponents.push(comp);
|
|
2868
|
+
}
|
|
2869
|
+
}
|
|
2870
|
+
|
|
2871
|
+
// Dessiner les composants scrollables
|
|
2872
|
+
if (scrollableComponents.length > 0) {
|
|
2873
|
+
this.ctx.save();
|
|
2874
|
+
this.ctx.translate(0, this.scrollOffset);
|
|
2875
|
+
|
|
2876
|
+
for (let comp of scrollableComponents) {
|
|
2877
|
+
if (comp.visible) {
|
|
2878
|
+
comp.draw(this.ctx);
|
|
2879
|
+
}
|
|
2880
|
+
}
|
|
2881
|
+
|
|
2882
|
+
this.ctx.restore();
|
|
2883
|
+
}
|
|
2884
|
+
|
|
2885
|
+
// Dessiner les composants fixes
|
|
2886
|
+
for (let comp of fixedComponents) {
|
|
2887
|
+
if (comp.visible) {
|
|
2888
|
+
comp.draw(this.ctx);
|
|
2889
|
+
}
|
|
2890
|
+
}
|
|
2891
|
+
|
|
2892
|
+
this.ctx.restore();
|
|
2893
|
+
}
|
|
2894
|
+
|
|
2899
2895
|
/**
|
|
2900
2896
|
* Mettre à jour la progression de la transition
|
|
2901
2897
|
* @private
|
|
@@ -3083,8 +3079,4 @@ class CanvasFramework {
|
|
|
3083
3079
|
}
|
|
3084
3080
|
}
|
|
3085
3081
|
|
|
3086
|
-
export default CanvasFramework;
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3082
|
+
export default CanvasFramework;
|