|
672 | 672 | if (!target) return; |
673 | 673 |
|
674 | 674 | event.preventDefault(); |
675 | | - const destination = scrollToTarget(hash); |
676 | | - window.dispatchEvent(new CustomEvent('modelized:navautoscroll', { |
677 | | - detail: { hash, destination } |
678 | | - })); |
| 675 | + scrollToTarget(hash); |
679 | 676 |
|
680 | 677 | const nav = document.querySelector('.nav'); |
681 | 678 | if (nav?.classList.contains('nav--open')){ |
|
798 | 795 |
|
799 | 796 | const homeSection = document.querySelector("#hero"); |
800 | 797 | let lockedHash = ""; |
801 | | - let lockedDestination = null; |
802 | | - let lockFrame = 0; |
803 | 798 | let lockTimer = 0; |
804 | 799 |
|
805 | 800 | const clearScrollLock = () => { |
806 | | - if (lockFrame) { |
807 | | - cancelAnimationFrame(lockFrame); |
808 | | - lockFrame = 0; |
809 | | - } |
810 | 801 | if (lockTimer) { |
811 | 802 | clearTimeout(lockTimer); |
812 | 803 | lockTimer = 0; |
813 | 804 | } |
814 | 805 | lockedHash = ""; |
815 | | - lockedDestination = null; |
816 | 806 | }; |
817 | 807 |
|
818 | 808 | const releaseScrollLock = () => { |
819 | 809 | clearScrollLock(); |
820 | 810 | syncFromViewport(); |
821 | 811 | }; |
822 | 812 |
|
823 | | - const watchScrollLock = () => { |
| 813 | + const scheduleScrollLockRelease = (delay = 140) => { |
824 | 814 | if (!lockedHash) return; |
825 | | - |
826 | | - let lastY = getScrollTop(); |
827 | | - let stillFrames = 0; |
828 | | - |
829 | | - const tick = () => { |
830 | | - lockFrame = 0; |
831 | | - if (!lockedHash) return; |
832 | | - |
833 | | - const currentY = getScrollTop(); |
834 | | - const delta = Math.abs(currentY - lastY); |
835 | | - const nearDestination = lockedDestination !== null && Math.abs(currentY - lockedDestination) <= 2; |
836 | | - |
837 | | - lastY = currentY; |
838 | | - stillFrames = (nearDestination || delta < 0.5) ? (stillFrames + 1) : 0; |
839 | | - |
840 | | - if (stillFrames >= 3) { |
841 | | - releaseScrollLock(); |
842 | | - return; |
843 | | - } |
844 | | - |
845 | | - lockFrame = requestAnimationFrame(tick); |
846 | | - }; |
847 | | - |
848 | | - lockFrame = requestAnimationFrame(tick); |
| 815 | + if (lockTimer) { |
| 816 | + clearTimeout(lockTimer); |
| 817 | + } |
| 818 | + lockTimer = window.setTimeout(releaseScrollLock, delay); |
849 | 819 | }; |
850 | 820 |
|
851 | 821 | setActiveByHash(location.hash); |
|
912 | 882 | map.forEach((_link, section) => observer.observe(section)); |
913 | 883 | requestAnimationFrame(syncFromViewport); |
914 | 884 |
|
915 | | - window.addEventListener('modelized:navautoscroll', (event) => { |
916 | | - const nextHash = event.detail?.hash; |
917 | | - if (!nextHash) return; |
918 | | - |
919 | | - clearScrollLock(); |
920 | | - lockedHash = nextHash; |
921 | | - lockedDestination = typeof event.detail?.destination === 'number' ? event.detail.destination : null; |
922 | | - setActiveByHash(lockedHash); |
923 | | - |
924 | | - if (prefersReducedMotion) { |
925 | | - lockTimer = window.setTimeout(releaseScrollLock, 0); |
926 | | - return; |
927 | | - } |
| 885 | + links.forEach((link) => { |
| 886 | + link.addEventListener('click', () => { |
| 887 | + const nextHash = link.getAttribute('href'); |
| 888 | + if (!nextHash || !nextHash.startsWith('#')) return; |
928 | 889 |
|
929 | | - lockTimer = window.setTimeout(watchScrollLock, 120); |
| 890 | + clearScrollLock(); |
| 891 | + lockedHash = nextHash; |
| 892 | + setActiveByHash(lockedHash); |
| 893 | + scheduleScrollLockRelease(prefersReducedMotion ? 0 : 180); |
| 894 | + }); |
930 | 895 | }); |
931 | 896 |
|
| 897 | + window.addEventListener('scroll', () => { |
| 898 | + scheduleScrollLockRelease(140); |
| 899 | + }, { passive: true }); |
| 900 | + |
932 | 901 | window.addEventListener('orientationchange', clearScrollLock); |
933 | | - window.addEventListener('resize', () => { |
934 | | - if (!lockedHash) return; |
935 | | - lockTimer = window.setTimeout(releaseScrollLock, 0); |
936 | | - }); |
| 902 | + window.addEventListener('resize', releaseScrollLock); |
937 | 903 | } |
938 | 904 |
|
939 | 905 | function initSectionDepth() { |
|
0 commit comments