| @ -34,6 +34,8 @@ | |||||
| <div id="div_after_zone"></div> | <div id="div_after_zone"></div> | ||||
| </template> | </template> | ||||
| <script src="log.js"></script> | |||||
| <script src="scroll.js"></script> | |||||
| <script src="zones.js"></script> | <script src="zones.js"></script> | ||||
| <script> | <script> | ||||
| @ -43,16 +45,6 @@ | |||||
| </script> | </script> | ||||
| <script> | <script> | ||||
| const scrollThrottleCallback = (callback, timeout) => { | |||||
| let wait = false; | |||||
| return () => { | |||||
| if (wait) return; | |||||
| callback.call(); | |||||
| wait = true; | |||||
| setTimeout(() => { wait = false; }, timeout); | |||||
| }; | |||||
| }; | |||||
| function addClassToElement(id,className){ | function addClassToElement(id,className){ | ||||
| const element=document.querySelector(id); | const element=document.querySelector(id); | ||||
| if (element) element.classList.add(className); | if (element) element.classList.add(className); | ||||
| @ -115,21 +107,19 @@ | |||||
| } | } | ||||
| } | } | ||||
| function scrollToElement(elementSelector) { | |||||
| const element = document.querySelector(elementSelector); | |||||
| if (element) { | |||||
| element.scrollIntoView(); | |||||
| logMsg('htmlElement','scrollTo '+elementSelector); | |||||
| } | |||||
| } | |||||
| // ---- | |||||
| // ---- La page est une machine à états | |||||
| // ---- | |||||
| let currentEtat = 1; | |||||
| let maxEtat = 4; | |||||
| function etatSections(etat) { | function etatSections(etat) { | ||||
| logMsg('etatSection','Etat courant '+etat); | |||||
| //if (currentEtat == etat) return; | |||||
| currentEtat=etat; | |||||
| logMsg('etatSection','Etat courant '+currentEtat); | |||||
| switch (etat) { | switch (etat) { | ||||
| case 1 : | case 1 : | ||||
| scrollToElement('#div_before_header'); | scrollToElement('#div_before_header'); | ||||
| section_header.style.display = "block"; | section_header.style.display = "block"; | ||||
| section_synthese.style.display = "block"; | |||||
| removeClassToElement('#div_navbar','navbar_fixed'); | removeClassToElement('#div_navbar','navbar_fixed'); | ||||
| removeClassToElement('#div_before_synthese','div_before_synthese_when_navbar_fixed'); | removeClassToElement('#div_before_synthese','div_before_synthese_when_navbar_fixed'); | ||||
| break; | break; | ||||
| @ -145,59 +135,55 @@ | |||||
| addClassToElement('#div_navbar','navbar_fixed'); | addClassToElement('#div_navbar','navbar_fixed'); | ||||
| addClassToElement('#div_before_synthese','div_before_synthese_when_navbar_fixed'); | addClassToElement('#div_before_synthese','div_before_synthese_when_navbar_fixed'); | ||||
| break; | break; | ||||
| default : | |||||
| break; | |||||
| } | } | ||||
| } | } | ||||
| let currentEtat=1; | |||||
| function changeEtatUp() { | function changeEtatUp() { | ||||
| if (++currentEtat > 3) currentEtat = 3; | |||||
| if (++currentEtat > maxEtat) currentEtat = maxEtat; | |||||
| etatSections(currentEtat); | etatSections(currentEtat); | ||||
| } | } | ||||
| function changeEtatDown(){ | function changeEtatDown(){ | ||||
| if (--currentEtat > 3) currentEtat = 1; | |||||
| if (--currentEtat < 1) currentEtat = 1; | |||||
| etatSections(currentEtat); | etatSections(currentEtat); | ||||
| } | } | ||||
| after_section_header.addEventListener("click", function() { | |||||
| logMsg('etatSection','toggle section_header '); | |||||
| if (currentEtat!=1) etatSections(1); | |||||
| else etatSections(2); | |||||
| }); | |||||
| after_section_synthese.addEventListener("click", function() { | after_section_synthese.addEventListener("click", function() { | ||||
| logMsg('etatSection','toggle section_synthese '); | logMsg('etatSection','toggle section_synthese '); | ||||
| if (currentEtat==3) changeEtatDown(); | if (currentEtat==3) changeEtatDown(); | ||||
| else changeEtatUp(); | else changeEtatUp(); | ||||
| }); | }); | ||||
| after_section_header.addEventListener("click", function() { | |||||
| logMsg('etatSection','toggle section_header '); | |||||
| if (currentEtat==2) changeEtatDown(); | |||||
| else changeEtatUp(); | |||||
| }); | |||||
| function beforeSection(_visible) { | |||||
| if (!_visible) changeEtatUp(); | |||||
| } | |||||
| function afterSection(_visible) { | |||||
| if (_visible) changeEtatDown(); | |||||
| } | |||||
| function beforeNavbarVisibility(_visible) { | |||||
| intersectionObserverLog('TRIGGER '+arguments.callee.name); | |||||
| beforeSection(_visible) | |||||
| } | |||||
| function afterNavbarVisibility(_visible) { | |||||
| intersectionObserverLog('TRIGGER '+arguments.callee.name); | |||||
| afterSection(_visible) | |||||
| } | |||||
| function beforeHeaderVisibility(_visible) { | function beforeHeaderVisibility(_visible) { | ||||
| intersectionObserverLog('TRIGGER '+arguments.callee.name); | intersectionObserverLog('TRIGGER '+arguments.callee.name); | ||||
| if (!_visible) { | |||||
| changeEtatUp(); | |||||
| } | |||||
| beforeSection(_visible) | |||||
| } | } | ||||
| function afterHeaderVisibility(_visible) { | function afterHeaderVisibility(_visible) { | ||||
| intersectionObserverLog('TRIGGER '+arguments.callee.name); | intersectionObserverLog('TRIGGER '+arguments.callee.name); | ||||
| if (_visible) { | |||||
| changeEtatDown(); | |||||
| } | |||||
| afterSection(_visible) | |||||
| } | } | ||||
| addIntersectionObserverEntry("div_before_header", beforeHeaderVisibility); | addIntersectionObserverEntry("div_before_header", beforeHeaderVisibility); | ||||
| addIntersectionObserverEntry("div_after_header", afterHeaderVisibility); | addIntersectionObserverEntry("div_after_header", afterHeaderVisibility); | ||||
| function beforeNavbarVisibility(_visible) { | |||||
| intersectionObserverLog('TRIGGER '+arguments.callee.name); | |||||
| if (!_visible) { | |||||
| changeEtatUp(); | |||||
| } | |||||
| } | |||||
| function afterNavbarVisibility(_visible) { | |||||
| intersectionObserverLog('TRIGGER '+arguments.callee.name); | |||||
| if (_visible) { | |||||
| changeEtatDown(); | |||||
| } | |||||
| } | |||||
| addIntersectionObserverEntry("div_before_navbar", beforeNavbarVisibility); | addIntersectionObserverEntry("div_before_navbar", beforeNavbarVisibility); | ||||
| //addIntersectionObserverEntry("div_after_navbar", afterNavbarVisibility); | //addIntersectionObserverEntry("div_after_navbar", afterNavbarVisibility); | ||||
| @ -0,0 +1,14 @@ | |||||
| const logMsgActivesSections = new Set(); | |||||
| function logMsgAddActiveSection(sectionName) { | |||||
| logMsgActivesSections.add(sectionName); | |||||
| } | |||||
| function logMsgRemoveActiveSection(sectionName) { | |||||
| logMsgActivesSections.delete(sectionName); | |||||
| } | |||||
| function logMsg(section, message){ | |||||
| if (logMsgActivesSections.has(section)) | |||||
| console.log(section, ' : ', message) | |||||
| } | |||||
| @ -0,0 +1,182 @@ | |||||
| const scrollThrottleCallback = (callback, timeout) => { | |||||
| let wait = false; | |||||
| return () => { | |||||
| if (wait) return; | |||||
| callback.call(); | |||||
| wait = true; | |||||
| setTimeout(() => { wait = false; }, timeout); | |||||
| }; | |||||
| }; | |||||
| function getAbsolutePosition(element) { | |||||
| const rect = element.getBoundingClientRect(); | |||||
| return { | |||||
| top: rect.top + window.scrollY, // Add vertical scroll | |||||
| left: rect.left + window.scrollX, // Add horizontal scroll | |||||
| bottom: rect.bottom + window.scrollY, | |||||
| right: rect.right + window.scrollX | |||||
| }; | |||||
| } | |||||
| function getPositionRelativeToParent(element) { | |||||
| const parent = element.parentElement; | |||||
| const parentRect = parent.getBoundingClientRect(); | |||||
| const elementRect = element.getBoundingClientRect(); | |||||
| return { | |||||
| top: elementRect.top - parentRect.top, | |||||
| left: elementRect.left - parentRect.left, | |||||
| bottom: elementRect.bottom - parentRect.top, | |||||
| right: elementRect.right - parentRect.left | |||||
| }; | |||||
| } | |||||
| function smoothScrollToElement(element, offset = 0) { | |||||
| const elementPosition = getAbsolutePosition(element); | |||||
| const targetScroll = elementPosition.top - offset; | |||||
| // Smooth scroll with animation | |||||
| window.scrollTo({ | |||||
| top: targetScroll, | |||||
| behavior: 'smooth' | |||||
| }); | |||||
| } | |||||
| // Enhanced version with progress callback | |||||
| function scrollToElementWithProgress(element, offset = 0, onProgress) { | |||||
| const start = window.scrollY; | |||||
| const elementPosition = getAbsolutePosition(element); | |||||
| const target = elementPosition.top - offset; | |||||
| const distance = target - start; | |||||
| const duration = 1000; // ms | |||||
| const startTime = performance.now(); | |||||
| function animate(currentTime) { | |||||
| const elapsed = currentTime - startTime; | |||||
| const progress = Math.min(elapsed / duration, 1); | |||||
| // Easing function for smooth animation | |||||
| const easeProgress = 1 - Math.pow(1 - progress, 3); | |||||
| const currentPosition = start + (distance * easeProgress); | |||||
| window.scrollTo(0, currentPosition); | |||||
| if (onProgress) { | |||||
| onProgress(progress); | |||||
| } | |||||
| if (progress < 1) { | |||||
| requestAnimationFrame(animate); | |||||
| } | |||||
| } | |||||
| requestAnimationFrame(animate); | |||||
| } | |||||
| function scrollToElement(elementSelector) { | |||||
| const element = document.querySelector(elementSelector); | |||||
| if (element) { | |||||
| const methode=1; | |||||
| switch (methode) { | |||||
| case 1 : | |||||
| element.scrollIntoView(); | |||||
| break; | |||||
| case 2 : | |||||
| smoothScrollToElement(element); | |||||
| break; | |||||
| case 3 : | |||||
| scrollToElementWithProgress(element, 0, (progress) => { | |||||
| logMsg('htmlElement',`Scroll progress: ${Math.round(progress * 100)}%`); | |||||
| }); | |||||
| break; | |||||
| } | |||||
| } | |||||
| logMsg('htmlElement','scrollTo '+elementSelector); | |||||
| } | |||||
| function getAbsolutePosition(element) { | |||||
| const rect = element.getBoundingClientRect(); | |||||
| return { | |||||
| top: rect.top + window.scrollY, // Add vertical scroll | |||||
| left: rect.left + window.scrollX, // Add horizontal scroll | |||||
| bottom: rect.bottom + window.scrollY, | |||||
| right: rect.right + window.scrollX | |||||
| }; | |||||
| } | |||||
| function getPositionRelativeToParent(element) { | |||||
| const parent = element.parentElement; | |||||
| const parentRect = parent.getBoundingClientRect(); | |||||
| const elementRect = element.getBoundingClientRect(); | |||||
| return { | |||||
| top: elementRect.top - parentRect.top, | |||||
| left: elementRect.left - parentRect.left, | |||||
| bottom: elementRect.bottom - parentRect.top, | |||||
| right: elementRect.right - parentRect.left | |||||
| }; | |||||
| } | |||||
| function smoothScrollToElement(element, offset = 0) { | |||||
| const elementPosition = getAbsolutePosition(element); | |||||
| const targetScroll = elementPosition.top - offset; | |||||
| // Smooth scroll with animation | |||||
| window.scrollTo({ | |||||
| top: targetScroll, | |||||
| behavior: 'smooth' | |||||
| }); | |||||
| } | |||||
| // Enhanced version with progress callback | |||||
| function scrollToElementWithProgress(element, offset = 0, onProgress) { | |||||
| const start = window.scrollY; | |||||
| const elementPosition = getAbsolutePosition(element); | |||||
| const target = elementPosition.top - offset; | |||||
| const distance = target - start; | |||||
| const duration = 1000; // ms | |||||
| const startTime = performance.now(); | |||||
| function animate(currentTime) { | |||||
| const elapsed = currentTime - startTime; | |||||
| const progress = Math.min(elapsed / duration, 1); | |||||
| // Easing function for smooth animation | |||||
| const easeProgress = 1 - Math.pow(1 - progress, 3); | |||||
| const currentPosition = start + (distance * easeProgress); | |||||
| window.scrollTo(0, currentPosition); | |||||
| if (onProgress) { | |||||
| onProgress(progress); | |||||
| } | |||||
| if (progress < 1) { | |||||
| requestAnimationFrame(animate); | |||||
| } | |||||
| } | |||||
| requestAnimationFrame(animate); | |||||
| } | |||||
| function scrollToElement(elementSelector) { | |||||
| const element = document.querySelector(elementSelector); | |||||
| if (element) { | |||||
| const methode=1; | |||||
| switch (methode) { | |||||
| case 1 : | |||||
| element.scrollIntoView(); | |||||
| break; | |||||
| case 2 : | |||||
| smoothScrollToElement(element); | |||||
| break; | |||||
| case 3 : | |||||
| scrollToElementWithProgress(element, 0, (progress) => { | |||||
| logMsg('htmlElement',`Scroll progress: ${Math.round(progress * 100)}%`); | |||||
| }); | |||||
| break; | |||||
| } | |||||
| } | |||||
| logMsg('htmlElement','scrollTo '+elementSelector); | |||||
| } | |||||
| @ -1,17 +1,3 @@ | |||||
| const logMsgActivesSections = new Set(); | |||||
| function logMsgAddActiveSection(sectionName) { | |||||
| logMsgActivesSections.add(sectionName); | |||||
| } | |||||
| function logMsgRemoveActiveSection(sectionName) { | |||||
| logMsgActivesSections.delete(sectionName); | |||||
| } | |||||
| function logMsg(section, message){ | |||||
| if (logMsgActivesSections.has(section)) | |||||
| console.log(section, ' : ', message) | |||||
| } | |||||
| function intersectionObserverLog(message) { | function intersectionObserverLog(message) { | ||||
| logMsg('intersectionObserver', message); | logMsg('intersectionObserver', message); | ||||