canvasframework 0.5.57 → 0.5.58
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/core/CanvasFramework.js +273 -94
- package/package.json +1 -1
package/core/CanvasFramework.js
CHANGED
|
@@ -374,7 +374,12 @@ class CanvasFramework {
|
|
|
374
374
|
};
|
|
375
375
|
this._firstRenderDone = false;
|
|
376
376
|
this._startupStartTime = startTime;
|
|
377
|
+
// Dans le constructeur, après this.scrollFriction = 0.95;
|
|
378
|
+
this.scrollFriction = 0.95;
|
|
377
379
|
|
|
380
|
+
// ✅ AJOUTER
|
|
381
|
+
this.overscrollDistance = 0;
|
|
382
|
+
this.isOverscrollAnimating = false;
|
|
378
383
|
// ✅ Créer automatiquement le canvas
|
|
379
384
|
this.canvas = document.createElement('canvas');
|
|
380
385
|
this.canvas.id = canvasId || `canvas-${Date.now()}`;
|
|
@@ -620,6 +625,7 @@ class CanvasFramework {
|
|
|
620
625
|
if (this.optimizations.useSpatialPartitioning) {
|
|
621
626
|
this._initSpatialPartitioning();
|
|
622
627
|
}
|
|
628
|
+
|
|
623
629
|
}
|
|
624
630
|
|
|
625
631
|
/**
|
|
@@ -688,7 +694,7 @@ class CanvasFramework {
|
|
|
688
694
|
* Crée le Worker pour le calcul du scroll
|
|
689
695
|
*/
|
|
690
696
|
createScrollWorker() {
|
|
691
|
-
|
|
697
|
+
const workerCode = `
|
|
692
698
|
let state = {
|
|
693
699
|
scrollOffset: 0,
|
|
694
700
|
scrollVelocity: 0,
|
|
@@ -697,7 +703,10 @@ class CanvasFramework {
|
|
|
697
703
|
maxScroll: 0,
|
|
698
704
|
height: 0,
|
|
699
705
|
lastTouchY: 0,
|
|
700
|
-
components: []
|
|
706
|
+
components: [],
|
|
707
|
+
overscrollDistance: 0,
|
|
708
|
+
maxOverscroll: 150, // ✅ Limite maximale
|
|
709
|
+
overscrollResistance: 0.3
|
|
701
710
|
};
|
|
702
711
|
|
|
703
712
|
const FIXED_COMPONENT_TYPES = [
|
|
@@ -708,13 +717,11 @@ class CanvasFramework {
|
|
|
708
717
|
|
|
709
718
|
const calculateMaxScroll = () => {
|
|
710
719
|
let maxY = 0;
|
|
711
|
-
|
|
712
720
|
for (const comp of state.components) {
|
|
713
721
|
if (FIXED_COMPONENT_TYPES.includes(comp.type) || !comp.visible) continue;
|
|
714
722
|
const bottom = comp.y + comp.height;
|
|
715
723
|
if (bottom > maxY) maxY = bottom;
|
|
716
724
|
}
|
|
717
|
-
|
|
718
725
|
return Math.max(0, maxY - state.height + 50);
|
|
719
726
|
};
|
|
720
727
|
|
|
@@ -722,7 +729,29 @@ class CanvasFramework {
|
|
|
722
729
|
if (Math.abs(state.scrollVelocity) > 0.1 && !state.isDragging) {
|
|
723
730
|
state.scrollOffset += state.scrollVelocity;
|
|
724
731
|
state.maxScroll = calculateMaxScroll();
|
|
725
|
-
|
|
732
|
+
|
|
733
|
+
// ✅ CORRIGER: Limiter l'overscroll pendant l'inertie
|
|
734
|
+
if (state.scrollOffset > 0) {
|
|
735
|
+
// Limiter à maxOverscroll
|
|
736
|
+
if (state.scrollOffset > state.maxOverscroll) {
|
|
737
|
+
state.scrollOffset = state.maxOverscroll;
|
|
738
|
+
state.scrollVelocity = 0;
|
|
739
|
+
}
|
|
740
|
+
state.overscrollDistance = state.scrollOffset;
|
|
741
|
+
state.scrollVelocity *= 0.85;
|
|
742
|
+
} else if (state.scrollOffset < -state.maxScroll) {
|
|
743
|
+
const excess = Math.abs(state.scrollOffset + state.maxScroll);
|
|
744
|
+
// Limiter à maxOverscroll
|
|
745
|
+
if (excess > state.maxOverscroll) {
|
|
746
|
+
state.scrollOffset = -state.maxScroll - state.maxOverscroll;
|
|
747
|
+
state.scrollVelocity = 0;
|
|
748
|
+
}
|
|
749
|
+
state.overscrollDistance = state.scrollOffset + state.maxScroll;
|
|
750
|
+
state.scrollVelocity *= 0.85;
|
|
751
|
+
} else {
|
|
752
|
+
state.overscrollDistance = 0;
|
|
753
|
+
}
|
|
754
|
+
|
|
726
755
|
state.scrollVelocity *= state.scrollFriction;
|
|
727
756
|
} else {
|
|
728
757
|
state.scrollVelocity = 0;
|
|
@@ -731,20 +760,82 @@ class CanvasFramework {
|
|
|
731
760
|
return {
|
|
732
761
|
scrollOffset: state.scrollOffset,
|
|
733
762
|
scrollVelocity: state.scrollVelocity,
|
|
734
|
-
maxScroll: state.maxScroll
|
|
763
|
+
maxScroll: state.maxScroll,
|
|
764
|
+
overscrollDistance: state.overscrollDistance
|
|
735
765
|
};
|
|
736
766
|
};
|
|
737
767
|
|
|
738
768
|
const handleTouchMove = (deltaY) => {
|
|
739
769
|
if (state.isDragging) {
|
|
740
|
-
state.scrollOffset += deltaY;
|
|
741
770
|
state.maxScroll = calculateMaxScroll();
|
|
742
|
-
|
|
771
|
+
const wouldBeOffset = state.scrollOffset + deltaY;
|
|
772
|
+
|
|
773
|
+
let actualDelta = deltaY;
|
|
774
|
+
|
|
775
|
+
// ✅ CORRIGER: Appliquer les limites d'overscroll
|
|
776
|
+
if (wouldBeOffset > 0) {
|
|
777
|
+
// Overscroll en haut
|
|
778
|
+
const currentOverscroll = state.scrollOffset > 0 ? state.scrollOffset : 0;
|
|
779
|
+
|
|
780
|
+
// Si on a déjà atteint la limite, ne plus bouger
|
|
781
|
+
if (currentOverscroll >= state.maxOverscroll) {
|
|
782
|
+
actualDelta = 0;
|
|
783
|
+
state.overscrollDistance = state.maxOverscroll;
|
|
784
|
+
} else {
|
|
785
|
+
// Calculer la résistance progressive
|
|
786
|
+
const overscrollRatio = currentOverscroll / state.maxOverscroll;
|
|
787
|
+
const resistance = state.overscrollResistance * (1 - overscrollRatio * 0.7);
|
|
788
|
+
|
|
789
|
+
actualDelta = deltaY * resistance;
|
|
790
|
+
|
|
791
|
+
// S'assurer qu'on ne dépasse pas la limite
|
|
792
|
+
const newOverscroll = currentOverscroll + actualDelta;
|
|
793
|
+
if (newOverscroll > state.maxOverscroll) {
|
|
794
|
+
actualDelta = state.maxOverscroll - currentOverscroll;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
state.overscrollDistance = currentOverscroll + actualDelta;
|
|
798
|
+
}
|
|
799
|
+
} else if (wouldBeOffset < -state.maxScroll) {
|
|
800
|
+
// Overscroll en bas
|
|
801
|
+
const currentOverscroll = state.scrollOffset < -state.maxScroll
|
|
802
|
+
? Math.abs(state.scrollOffset + state.maxScroll)
|
|
803
|
+
: 0;
|
|
804
|
+
|
|
805
|
+
// Si on a déjà atteint la limite, ne plus bouger
|
|
806
|
+
if (currentOverscroll >= state.maxOverscroll) {
|
|
807
|
+
actualDelta = 0;
|
|
808
|
+
state.overscrollDistance = -state.maxOverscroll;
|
|
809
|
+
} else {
|
|
810
|
+
// Calculer la résistance progressive
|
|
811
|
+
const overscrollRatio = currentOverscroll / state.maxOverscroll;
|
|
812
|
+
const resistance = state.overscrollResistance * (1 - overscrollRatio * 0.7);
|
|
813
|
+
|
|
814
|
+
actualDelta = deltaY * resistance;
|
|
815
|
+
|
|
816
|
+
// S'assurer qu'on ne dépasse pas la limite
|
|
817
|
+
const newOverscroll = currentOverscroll + Math.abs(actualDelta);
|
|
818
|
+
if (newOverscroll > state.maxOverscroll) {
|
|
819
|
+
actualDelta = deltaY > 0
|
|
820
|
+
? state.maxOverscroll - currentOverscroll
|
|
821
|
+
: -(state.maxOverscroll - currentOverscroll);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
state.overscrollDistance = -(currentOverscroll + Math.abs(actualDelta));
|
|
825
|
+
}
|
|
826
|
+
} else {
|
|
827
|
+
// Scroll normal
|
|
828
|
+
state.overscrollDistance = 0;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
state.scrollOffset += actualDelta;
|
|
743
832
|
state.scrollVelocity = deltaY;
|
|
833
|
+
|
|
744
834
|
return {
|
|
745
835
|
scrollOffset: state.scrollOffset,
|
|
746
836
|
scrollVelocity: state.scrollVelocity,
|
|
747
|
-
maxScroll: state.maxScroll
|
|
837
|
+
maxScroll: state.maxScroll,
|
|
838
|
+
overscrollDistance: state.overscrollDistance
|
|
748
839
|
};
|
|
749
840
|
}
|
|
750
841
|
return null;
|
|
@@ -755,16 +846,14 @@ class CanvasFramework {
|
|
|
755
846
|
|
|
756
847
|
switch (type) {
|
|
757
848
|
case 'INIT':
|
|
758
|
-
state = {
|
|
759
|
-
...state,
|
|
760
|
-
...payload
|
|
761
|
-
};
|
|
849
|
+
state = { ...state, ...payload };
|
|
762
850
|
state.maxScroll = calculateMaxScroll();
|
|
763
851
|
self.postMessage({
|
|
764
852
|
type: 'INITIALIZED',
|
|
765
853
|
payload: {
|
|
766
854
|
scrollOffset: state.scrollOffset,
|
|
767
|
-
maxScroll: state.maxScroll
|
|
855
|
+
maxScroll: state.maxScroll,
|
|
856
|
+
overscrollDistance: 0
|
|
768
857
|
}
|
|
769
858
|
});
|
|
770
859
|
break;
|
|
@@ -817,12 +906,43 @@ class CanvasFramework {
|
|
|
817
906
|
case 'SET_SCROLL_OFFSET':
|
|
818
907
|
state.scrollOffset = payload.scrollOffset;
|
|
819
908
|
state.maxScroll = calculateMaxScroll();
|
|
820
|
-
state.
|
|
909
|
+
state.overscrollDistance = 0;
|
|
910
|
+
self.postMessage({
|
|
911
|
+
type: 'SCROLL_UPDATED',
|
|
912
|
+
payload: {
|
|
913
|
+
scrollOffset: state.scrollOffset,
|
|
914
|
+
maxScroll: state.maxScroll,
|
|
915
|
+
overscrollDistance: 0
|
|
916
|
+
}
|
|
917
|
+
});
|
|
918
|
+
break;
|
|
919
|
+
|
|
920
|
+
case 'ANIMATE_RETURN':
|
|
921
|
+
state.maxScroll = calculateMaxScroll();
|
|
922
|
+
|
|
923
|
+
if (state.scrollOffset > 0) {
|
|
924
|
+
state.scrollOffset *= 0.75;
|
|
925
|
+
state.overscrollDistance = state.scrollOffset;
|
|
926
|
+
} else if (state.scrollOffset < -state.maxScroll) {
|
|
927
|
+
const diff = state.scrollOffset + state.maxScroll;
|
|
928
|
+
state.scrollOffset = -state.maxScroll + (diff * 0.75);
|
|
929
|
+
state.overscrollDistance = diff * 0.75;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
const shouldContinue = Math.abs(state.overscrollDistance) > 1;
|
|
933
|
+
|
|
934
|
+
if (!shouldContinue) {
|
|
935
|
+
state.scrollOffset = Math.max(Math.min(state.scrollOffset, 0), -state.maxScroll);
|
|
936
|
+
state.overscrollDistance = 0;
|
|
937
|
+
}
|
|
938
|
+
|
|
821
939
|
self.postMessage({
|
|
822
940
|
type: 'SCROLL_UPDATED',
|
|
823
941
|
payload: {
|
|
824
942
|
scrollOffset: state.scrollOffset,
|
|
825
|
-
maxScroll: state.maxScroll
|
|
943
|
+
maxScroll: state.maxScroll,
|
|
944
|
+
overscrollDistance: state.overscrollDistance,
|
|
945
|
+
shouldContinue
|
|
826
946
|
}
|
|
827
947
|
});
|
|
828
948
|
break;
|
|
@@ -834,7 +954,8 @@ class CanvasFramework {
|
|
|
834
954
|
scrollOffset: state.scrollOffset,
|
|
835
955
|
scrollVelocity: state.scrollVelocity,
|
|
836
956
|
maxScroll: state.maxScroll,
|
|
837
|
-
isDragging: state.isDragging
|
|
957
|
+
isDragging: state.isDragging,
|
|
958
|
+
overscrollDistance: state.overscrollDistance
|
|
838
959
|
}
|
|
839
960
|
});
|
|
840
961
|
break;
|
|
@@ -842,64 +963,71 @@ class CanvasFramework {
|
|
|
842
963
|
};
|
|
843
964
|
`;
|
|
844
965
|
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
return new Worker(URL.createObjectURL(blob));
|
|
849
|
-
}
|
|
966
|
+
const blob = new Blob([workerCode], { type: 'application/javascript' });
|
|
967
|
+
return new Worker(URL.createObjectURL(blob));
|
|
968
|
+
}
|
|
850
969
|
|
|
851
970
|
/**
|
|
852
971
|
* Gère les messages du Scroll Worker
|
|
853
972
|
*/
|
|
854
973
|
handleScrollWorkerMessage(e) {
|
|
855
|
-
|
|
856
|
-
type,
|
|
857
|
-
payload
|
|
858
|
-
} = e.data;
|
|
974
|
+
const { type, payload } = e.data;
|
|
859
975
|
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
this.
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
this.components.forEach(comp => {
|
|
875
|
-
if (!this.isFixedComponent(comp)) {
|
|
876
|
-
this.markComponentDirty(comp);
|
|
877
|
-
}
|
|
878
|
-
});
|
|
879
|
-
}
|
|
880
|
-
break;
|
|
976
|
+
switch (type) {
|
|
977
|
+
case 'SCROLL_UPDATED':
|
|
978
|
+
this.scrollOffset = payload.scrollOffset;
|
|
979
|
+
this.scrollVelocity = payload.scrollVelocity;
|
|
980
|
+
|
|
981
|
+
// ✅ AJOUTER
|
|
982
|
+
this.overscrollDistance = payload.overscrollDistance || 0;
|
|
983
|
+
|
|
984
|
+
if (Math.abs(payload.scrollVelocity) > 0.5) {
|
|
985
|
+
this.dirtyComponents.clear();
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
this._cachedMaxScroll = payload.maxScroll;
|
|
989
|
+
this._maxScrollDirty = false;
|
|
881
990
|
|
|
882
|
-
|
|
883
|
-
this.
|
|
884
|
-
|
|
885
|
-
|
|
991
|
+
if (Math.abs(payload.scrollVelocity) > 0) {
|
|
992
|
+
this.components.forEach(comp => {
|
|
993
|
+
if (!this.isFixedComponent(comp)) {
|
|
994
|
+
this.markComponentDirty(comp);
|
|
995
|
+
}
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
// ✅ AJOUTER: Continuer l'animation de retour si nécessaire
|
|
1000
|
+
if (payload.shouldContinue !== undefined && payload.shouldContinue) {
|
|
1001
|
+
requestAnimationFrame(() => {
|
|
1002
|
+
this.scrollWorker.postMessage({ type: 'ANIMATE_RETURN' });
|
|
1003
|
+
});
|
|
1004
|
+
} else if (payload.shouldContinue === false) {
|
|
1005
|
+
this.isOverscrollAnimating = false;
|
|
1006
|
+
}
|
|
1007
|
+
break;
|
|
886
1008
|
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
break;
|
|
1009
|
+
case 'MAX_SCROLL_UPDATED':
|
|
1010
|
+
this._cachedMaxScroll = payload.maxScroll;
|
|
1011
|
+
this._maxScrollDirty = false;
|
|
1012
|
+
break;
|
|
892
1013
|
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
1014
|
+
case 'INITIALIZED':
|
|
1015
|
+
this.scrollOffset = payload.scrollOffset;
|
|
1016
|
+
this._cachedMaxScroll = payload.maxScroll;
|
|
1017
|
+
this._maxScrollDirty = false;
|
|
1018
|
+
this.overscrollDistance = 0; // ✅ AJOUTER
|
|
1019
|
+
break;
|
|
1020
|
+
|
|
1021
|
+
case 'STATE':
|
|
1022
|
+
this.scrollOffset = payload.scrollOffset;
|
|
1023
|
+
this.scrollVelocity = payload.scrollVelocity;
|
|
1024
|
+
this.isDragging = payload.isDragging;
|
|
1025
|
+
this._cachedMaxScroll = payload.maxScroll;
|
|
1026
|
+
this._maxScrollDirty = false;
|
|
1027
|
+
this.overscrollDistance = payload.overscrollDistance || 0; // ✅ AJOUTER
|
|
1028
|
+
break;
|
|
902
1029
|
}
|
|
1030
|
+
}
|
|
903
1031
|
|
|
904
1032
|
/**
|
|
905
1033
|
* Initialise le Scroll Worker avec les données actuelles
|
|
@@ -2311,23 +2439,29 @@ class CanvasFramework {
|
|
|
2311
2439
|
}
|
|
2312
2440
|
|
|
2313
2441
|
handleTouchEnd(e) {
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2442
|
+
e.preventDefault();
|
|
2443
|
+
const touch = e.changedTouches[0];
|
|
2444
|
+
const pos = this.getTouchPos(touch);
|
|
2317
2445
|
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2446
|
+
if (!this.isDragging) {
|
|
2447
|
+
this.checkComponentsAtPosition(pos.x, pos.y, 'end');
|
|
2448
|
+
} else {
|
|
2449
|
+
this.isDragging = false;
|
|
2450
|
+
this.scrollWorker.postMessage({
|
|
2451
|
+
type: 'SET_DRAGGING',
|
|
2452
|
+
payload: {
|
|
2453
|
+
isDragging: false,
|
|
2454
|
+
lastVelocity: this.scrollVelocity
|
|
2455
|
+
}
|
|
2456
|
+
});
|
|
2457
|
+
|
|
2458
|
+
// ✅ AJOUTER: Démarrer l'animation de retour
|
|
2459
|
+
if (!this.isOverscrollAnimating) {
|
|
2460
|
+
this.isOverscrollAnimating = true;
|
|
2461
|
+
this.scrollWorker.postMessage({ type: 'ANIMATE_RETURN' });
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
}
|
|
2331
2465
|
|
|
2332
2466
|
handleMouseDown(e) {
|
|
2333
2467
|
this.isDragging = false;
|
|
@@ -2375,21 +2509,26 @@ class CanvasFramework {
|
|
|
2375
2509
|
}
|
|
2376
2510
|
}
|
|
2377
2511
|
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2512
|
+
handleMouseUp(e) {
|
|
2513
|
+
if (!this.isDragging) {
|
|
2514
|
+
this.checkComponentsAtPosition(e.clientX, e.clientY, 'end');
|
|
2515
|
+
} else {
|
|
2516
|
+
this.isDragging = false;
|
|
2517
|
+
this.scrollWorker.postMessage({
|
|
2518
|
+
type: 'SET_DRAGGING',
|
|
2519
|
+
payload: {
|
|
2520
|
+
isDragging: false,
|
|
2521
|
+
lastVelocity: this.scrollVelocity
|
|
2522
|
+
}
|
|
2523
|
+
});
|
|
2524
|
+
|
|
2525
|
+
// ✅ AJOUTER: Démarrer l'animation de retour
|
|
2526
|
+
if (!this.isOverscrollAnimating) {
|
|
2527
|
+
this.isOverscrollAnimating = true;
|
|
2528
|
+
this.scrollWorker.postMessage({ type: 'ANIMATE_RETURN' });
|
|
2390
2529
|
}
|
|
2391
2530
|
}
|
|
2392
|
-
|
|
2531
|
+
}
|
|
2393
2532
|
|
|
2394
2533
|
getTouchPos(touch) {
|
|
2395
2534
|
const rect = this.canvas.getBoundingClientRect();
|
|
@@ -2988,6 +3127,46 @@ class CanvasFramework {
|
|
|
2988
3127
|
this.renderFull();
|
|
2989
3128
|
}
|
|
2990
3129
|
}
|
|
3130
|
+
|
|
3131
|
+
/**
|
|
3132
|
+
* Dessine l'effet d'overscroll (overlay gris)
|
|
3133
|
+
*/
|
|
3134
|
+
drawOverscrollEffect() {console.log('dessine');
|
|
3135
|
+
if (Math.abs(this.overscrollDistance) < 1) return;
|
|
3136
|
+
|
|
3137
|
+
const ctx = this.ctx;
|
|
3138
|
+
ctx.save();
|
|
3139
|
+
|
|
3140
|
+
// Calculer l'opacité (max 0.4 pour Android)
|
|
3141
|
+
const maxOverscroll = 150;
|
|
3142
|
+
const opacity = Math.min(Math.abs(this.overscrollDistance) / maxOverscroll, 1) * 0.4;
|
|
3143
|
+
|
|
3144
|
+
// Hauteur de l'overlay
|
|
3145
|
+
const overlayHeight = Math.min(Math.abs(this.overscrollDistance) * 1.2, 250);
|
|
3146
|
+
|
|
3147
|
+
let gradient;
|
|
3148
|
+
|
|
3149
|
+
// Overscroll en haut
|
|
3150
|
+
if (this.overscrollDistance > 0) {
|
|
3151
|
+
gradient = ctx.createLinearGradient(0, 0, 0, overlayHeight);
|
|
3152
|
+
gradient.addColorStop(0, `rgba(100, 100, 100, ${opacity})`);
|
|
3153
|
+
gradient.addColorStop(1, 'rgba(100, 100, 100, 0)');
|
|
3154
|
+
|
|
3155
|
+
ctx.fillStyle = gradient;
|
|
3156
|
+
ctx.fillRect(0, 0, this.width, overlayHeight);
|
|
3157
|
+
}
|
|
3158
|
+
// Overscroll en bas
|
|
3159
|
+
else if (this.overscrollDistance < 0) {
|
|
3160
|
+
gradient = ctx.createLinearGradient(0, this.height - overlayHeight, 0, this.height);
|
|
3161
|
+
gradient.addColorStop(0, 'rgba(100, 100, 100, 0)');
|
|
3162
|
+
gradient.addColorStop(1, `rgba(100, 100, 100, ${opacity})`);
|
|
3163
|
+
|
|
3164
|
+
ctx.fillStyle = gradient;
|
|
3165
|
+
ctx.fillRect(0, this.height - overlayHeight, this.width, overlayHeight);
|
|
3166
|
+
}
|
|
3167
|
+
|
|
3168
|
+
ctx.restore();
|
|
3169
|
+
}
|
|
2991
3170
|
|
|
2992
3171
|
/**
|
|
2993
3172
|
* Rendu normal (sans transition)
|