diff --git a/resources/scripts/app.js b/resources/scripts/app.js index 8ba1691..00146ca 100644 --- a/resources/scripts/app.js +++ b/resources/scripts/app.js @@ -43,7 +43,7 @@ domReady(async () => { } } // italiques -> A FAIRE SUR LE CSV AVANT D'IMPORTER CA RALENTIT DE OUF LE CHARGEMENT -/* let tbody = document.querySelector('body main table tbody'); + /* let tbody = document.querySelector('body main table tbody'); let tbodyContent = tbody.innerHTML; let asteriskCounter = 0; for (let i = 0; i < tbodyContent.length; i++) { @@ -128,17 +128,18 @@ domReady(async () => { } let totalTime = convertToSeconds(lastTime[0].innerText); - let tlContainer, tlContainerHeight; - var bodyHeight = document.querySelector('body').offsetHeight; + let tlContainer, tlContainerHeight, bodyHeight; let partBlockHeights = []; let activePartIndex = 0; - + function getAllHeights() { partBlockHeights = []; tlContainer = document.querySelector('#timeline_container'); - tlContainer.style.height = `calc(100vh - ${document.querySelector('header').offsetHeight}px - ${document.querySelector('footer').offsetHeight}px - 60px)`; + let header = document.querySelector('header'), footer = document.querySelector('footer'); + tlContainer.style.height = `calc(100vh - ${header.offsetHeight}px - ${footer.offsetHeight}px - 60px)`; tlContainer.style.top = `${document.querySelector('header').offsetHeight + 30}px`; tlContainerHeight = tlContainer.offsetHeight; + bodyHeight = document.querySelector('body').offsetHeight; for (let partDuration of partDurations) { partBlockHeights.push(partDuration / totalTime * tlContainerHeight); } @@ -178,7 +179,6 @@ domReady(async () => { drawFriseRects(); window.addEventListener('resize', () => { - bodyHeight = document.querySelector('body').offsetHeight; while(tlContainer.lastChild) { tlContainer.removeChild(tlContainer.lastChild); } @@ -230,92 +230,29 @@ domReady(async () => { } titreFriseEl.setAttribute('id', 'titres_frise'); - titreFriseEl.innerHTML = `

${getCurrentTime(titresFrise[0].el)}

${titresFrise[0].main}

${titresFrise[0].sub}

`; - titreFriseEl.style.fontSize = "0.9em"; + titreFriseEl.innerHTML = ` +

${getCurrentTime(titresFrise[0].el)}

+

${titresFrise[0].main}

+

${titresFrise[0].sub}

+ `; + titreFriseEl.style.fontSize = '0.9em'; titreFriseEl.style.zIndex = '0'; - titreFriseEl.style.position = "fixed"; - titreFriseEl.style.left = "60px"; - titreFriseEl.style.width = "10vw"; - titreFriseEl.style.lineHeight = "1.2"; - titreFriseEl.style.top = `${document.querySelector('#timeline_container').getBoundingClientRect().top - 8}px`; + titreFriseEl.style.position = 'fixed'; + titreFriseEl.style.left = '60px'; + titreFriseEl.style.width = '10vw'; + titreFriseEl.style.lineHeight = '1.2'; + titreFriseEl.style.marginTop = '-8px'; + titreFriseEl.style.top = `${document.querySelector('#timeline_container').getBoundingClientRect().top}px`; let main = document.querySelector('#main'); main.prepend(titreFriseEl); - // make the cursor move on scroll - let cursor = document.querySelector('#cursor'); - let isCursorGrabbed = false; - cursor.style.top = `${document.querySelector('#timeline_container').getBoundingClientRect().top}px`; - let cursorPrevTranslateAmount = +cursor.style.transform.slice(0, -3).slice(11); - document.addEventListener("scroll", (event) => { - if (!isCursorGrabbed) { - scrollMovement(); - } - }); - // make the cursor draggable - let prevMousePos = 0; - cursor.addEventListener("mousedown", (event) => { - if (!isCursorGrabbed) { - event.preventDefault(); - isCursorGrabbed = true; - prevMousePos = event.clientY; - } - }); - window.addEventListener("mousemove", (event) => { - if (isCursorGrabbed) { - event.preventDefault(); - let newPos = cursorPrevTranslateAmount + (event.clientY - prevMousePos); - if (event.clientY < tlContainerHeight + tlContainer.offsetTop && event.clientY > tlContainer.offsetTop) { - cursor.style.transform = `translateY(${newPos}px)`; - window.scrollBy(0, (event.clientY - prevMousePos) * (bodyHeight / tlContainerHeight)); - cursorPrevTranslateAmount = +cursor.style.transform.slice(0, -3).slice(11); - } else if (event.clientY <= tlContainer.offsetTop) { - cursor.style.transform = "translateY(0px)"; - window.scroll(0, 0); - cursorPrevTranslateAmount = 0; - } else if (event.clientY >= tlContainerHeight + tlContainer.offsetTop) { - cursor.style.transform = `translateY(${tlContainerHeight}px)`; - window.scroll(0, bodyHeight); - cursorPrevTranslateAmount = +cursor.style.transform.slice(0, -3).slice(11); - } - prevMousePos = event.clientY; - } - }); - window.addEventListener("mouseup", (event) => { - if (isCursorGrabbed) { - isCursorGrabbed = false; - } - }); - - function getSteps() { - let partRects = document.querySelectorAll('#timeline_container div'); - let tlElSteps = []; - let total = 0; - for (let i = 0; i < partRects.length; i++) { - total = total + partRects[i].clientHeight; - if (i === 0) total = total - partRects[0].clientHeight; - tlElSteps.push(total); - } - let titles = document.querySelectorAll('.isMainPart, .isSubPart'); - let scrollSteps = []; - for (let title of titles) { - let nextLine = title.nextElementSibling; - if (!nextLine?.classList.contains('isSubPart')) { - scrollSteps.push(title.offsetTop); - } - } - return({ - 'tlElSteps':tlElSteps, - 'scrollSteps':scrollSteps - }); - } - + // création et togle des titres au survol des div de la timeline function drawFixedTitles() { let tlContainer = document.querySelector('#timeline_container'); let fixedTitlesContainer = document.createElement('div'); fixedTitlesContainer.setAttribute('id', 'fixedTitlesContainer'); main.prepend(fixedTitlesContainer); - let index = 0; - for (let titreFrise of titresFrise) { + for (let index = 0; index < titresFrise.length; index++) { let titreFixedEl = document.createElement('div'); titreFixedEl.style.position = 'fixed'; titreFixedEl.style.zIndex = 1; @@ -328,7 +265,10 @@ domReady(async () => { titreFixedEl.style.fontSize = '0.9em'; titreFixedEl.style.lineHeight = '1.2'; let titreFixedElContent = document.createElement('p'); - titreFixedElContent.innerHTML = `

${titresFrise[titresFrise.length - index - 1].main}

${titresFrise[titresFrise.length - index - 1].sub}

`; + titreFixedElContent.innerHTML = ` +

${titresFrise[titresFrise.length - index - 1].main}

+

${titresFrise[titresFrise.length - index - 1].sub}

+ `; titreFixedElContent.style.backgroundColor = '#010d19'; titreFixedEl.append(titreFixedElContent); let topGradient = document.createElement('div'); @@ -342,7 +282,6 @@ domReady(async () => { bottomGradient.style.background = 'linear-gradient(to top, transparent, #010d19)'; titreFixedEl.append(bottomGradient); fixedTitlesContainer.prepend(titreFixedEl); - index++; } } drawFixedTitles(); @@ -363,75 +302,203 @@ domReady(async () => { } } - function cursorMovement() { - } - + // make the cursor move on scroll + let cursor = document.querySelector('#cursor'); + cursor.style.top = `${document.querySelector('#timeline_container').getBoundingClientRect().top}px`; + cursor.style.cursor = 'grab'; let titres = document.querySelector('#titres_frise'); - let prevPartIndex = 0; + titres.style.cursor = 'grab'; let partRects = document.querySelectorAll('#timeline_container div'); partRects = Array.from(partRects); partRects = partRects.reverse(); partRects[0].style.width = '32px'; + let grabbing = false; + document.addEventListener("scroll", (event) => { + if (!grabbing) { + displayCurrentPartTitle(getCurrentPartFromScroll()); + moveCursorFromScroll(getCurrentPartFromScroll()); + } + }); - function scrollMovement() { + function makeElementDraggable(element, relatedEl) { + let offsetY; + + element.addEventListener('mousedown', (e) => { + e.preventDefault(); + grabbing = true; + offsetY = e.clientY - +element.style.top.slice(0, -2); + element.style.cursor = 'grabbing'; + }); + + document.addEventListener('mousemove', (e) => { + if (grabbing) { + if (e.clientY < tlContainerHeight + tlContainer.offsetTop && e.clientY > tlContainer.offsetTop) { + const y = e.clientY - offsetY; + element.style.top = `${y}px`; + relatedEl.style.top = `${y}px`; + if (!isNaN(y)) displayCurrentPartTitle(getCurrentPartFromCursor(y)); + } else if (e.clientY <= tlContainer.offsetTop) { + element.style.top = `${tlContainer.offsetTop}px`; + relatedEl.style.top = `${tlContainer.offsetTop}px`; + } else if (e.clientY >= tlContainerHeight + tlContainer.offsetTop) { + element.style.top = `${tlContainerHeight + tlContainer.offsetTop}px`; + relatedEl.style.top = `${tlContainerHeight + tlContainer.offsetTop}px`; + } + } + }); + + document.addEventListener('mouseup', () => { + grabbing = false; + element.style.cursor = 'grab'; + }); + } + + makeElementDraggable(cursor, titres); + makeElementDraggable(titres, cursor); + + + + + + +/* let cursorPrevTranslateAmount = +cursor.style.transform.slice(0, -3).slice(11); + // make the cursor draggable + let prevMousePos = 0; + cursor.addEventListener("mousedown", (event) => { + if (!grabbing) { + event.preventDefault(); + grabbing = true; + prevMousePos = event.clientY; + } + }); + window.addEventListener("mousemove", (event) => { + if (grabbing) { + event.preventDefault(); + let newPos = cursorPrevTranslateAmount + (event.clientY - prevMousePos); + if (event.clientY < tlContainerHeight + tlContainer.offsetTop && event.clientY > tlContainer.offsetTop) { + cursor.style.transform = `translateY(${newPos}px)`; + window.scrollBy(0, (event.clientY - prevMousePos) * (bodyHeight / tlContainerHeight)); + cursorPrevTranslateAmount = +cursor.style.transform.slice(0, -3).slice(11); + } else if (event.clientY <= tlContainer.offsetTop) { + cursor.style.transform = "translateY(0px)"; + window.scroll(0, 0); + cursorPrevTranslateAmount = 0; + } else if (event.clientY >= tlContainerHeight + tlContainer.offsetTop) { + cursor.style.transform = `translateY(${tlContainerHeight}px)`; + window.scroll(0, bodyHeight); + cursorPrevTranslateAmount = +cursor.style.transform.slice(0, -3).slice(11); + } + prevMousePos = event.clientY; + } + }); + window.addEventListener("mouseup", (event) => { + if (grabbing) { + grabbing = false; + } + }); + */ + + + + + + // get heights of parts dans le tableau et dans la timeline + function getSteps() { + let tlElSteps = []; + for (let i = 0; i < partRects.length; i++) { + tlElSteps.push(partRects[i].offsetTop); + } + let titles = document.querySelectorAll('.isMainPart, .isSubPart'); + let scrollSteps = []; + for (let title of titles) { + let nextLine = title.nextElementSibling; + if (!nextLine?.classList.contains('isSubPart')) { + scrollSteps.push(title.offsetTop); + } + } + return({ + 'tlElSteps':tlElSteps, + 'scrollSteps':scrollSteps + }); + } + + function moveCursorFromScroll(currentPartIndex) { let currentScroll = window.scrollY; let cursorTopValue = 0; let tlPartHeight, tlPartBottom; - + for (let j = 0; j < partRects.length; j++) { + tlPartHeight = partRects[j].getBoundingClientRect().height + tlPartBottom = partRects[j].getBoundingClientRect().top - tlContainer.getBoundingClientRect().top; + cursorTopValue = tlPartBottom; + // get the amount of the current scrollpart scrolled + if (j === currentPartIndex) break; + } + + let currentScrollPartBottom = getSteps().scrollSteps[currentPartIndex - 1] ? getSteps().scrollSteps[currentPartIndex - 1] : 0; + let currentScrollPartHeight; + if (getSteps().scrollSteps[currentPartIndex + 1]) { + currentScrollPartHeight = getSteps().scrollSteps[currentPartIndex + 1] - currentScrollPartBottom; + } else { + currentScrollPartHeight = document.querySelector('body').scrollHeight - currentScrollPartBottom; + } + let currentScrollSincePartBottom = currentScroll - currentScrollPartBottom; + let scrollPartProportion = currentScrollSincePartBottom / currentScrollPartHeight; + + cursorTopValue = cursorTopValue + tlPartHeight * (tlPartHeight / tlPartHeight * (scrollPartProportion - 0.3)); + + if (cursorTopValue > 0) { + cursor.style.transform = `translateY(${cursorTopValue}px)`; + titres.style.transform = `translateY(${cursorTopValue}px)`; + } else { + cursor.style.transform = `translateY(0px)`; + titres.style.transform = `translateY(0px)`; + } + } + + let prevPartIndex = 0; + + function displayCurrentPartTitle(currentPartIndex) { + titres.firstElementChild.innerText = getCurrentTime(titresFrise[currentPartIndex]?.el); + let mainEl = titres.children[1]; + let subEl = titres.lastElementChild; + if (mainEl.innerText != titresFrise[currentPartIndex]?.main || subEl.innerText != titresFrise[currentPartIndex]?.sub) { + mainEl.innerText = titresFrise[currentPartIndex]?.main; + subEl.innerText = titresFrise[currentPartIndex]?.sub; + partRects[prevPartIndex].style.width = '22px'; + partRects[currentPartIndex].style.width = '32px'; + } + activePartIndex = currentPartIndex; + prevPartIndex = currentPartIndex; + } + + function getCurrentPartFromScroll() { + let currentScroll = window.scrollY; for (let i = 0; i < getSteps().scrollSteps.length; i++) { - if ((currentScroll >= getSteps().scrollSteps[i] && currentScroll <= getSteps().scrollSteps[i + 1]) || - (currentScroll >= getSteps().scrollSteps[i] && i === getSteps().scrollSteps.length - 1)) { - // titres et temps - titres.firstElementChild.innerText = getCurrentTime(titresFrise[i].el); - let mainEl = titres.children[1]; - let subEl = titres.lastElementChild; - if (mainEl.innerText != titresFrise[i].main || subEl.innerText != titresFrise[i].sub) { - mainEl.innerText = titresFrise[i].main; - subEl.innerText = titresFrise[i].sub; - partRects[prevPartIndex].style.width = '22px'; - partRects[i].style.width = '32px'; - } - activePartIndex = i; - prevPartIndex = i; - - // curseur - for (let j = 0; j < partRects.length; j++) { - tlPartHeight = partRects[j].getBoundingClientRect().height - tlPartBottom = partRects[j].getBoundingClientRect().top - tlContainer.getBoundingClientRect().top; - cursorTopValue = tlPartBottom; - // get the amount of the current scrollpart scrolled - if (j === i) break; - } - - let currentScrollPartBottom = getSteps().scrollSteps[i - 1] ? getSteps().scrollSteps[i - 1] : 0; - let currentScrollPartHeight; - if (getSteps().scrollSteps[i + 1]) { - currentScrollPartHeight = getSteps().scrollSteps[i + 1] - currentScrollPartBottom; - } else { - currentScrollPartHeight = document.querySelector('body').scrollHeight - currentScrollPartBottom; - } - let currentScrollSincePartBottom = currentScroll - currentScrollPartBottom; - let scrollPartProportion = currentScrollSincePartBottom / currentScrollPartHeight; - - cursorTopValue = cursorTopValue + tlPartHeight * (tlPartHeight / tlPartHeight * (scrollPartProportion - 0.3)); - - if (cursorTopValue > 0) { - cursor.style.transform = `translateY(${cursorTopValue}px)`; - titres.style.transform = `translateY(${cursorTopValue}px)`; - } else { - cursor.style.transform = `translateY(0px)`; - titres.style.transform = `translateY(0px)`; - } - - break; + if ( + (currentScroll + window.innerHeight / 2 >= getSteps().scrollSteps[i] + && currentScroll + window.innerHeight / 2 <= getSteps().scrollSteps[i + 1]) || + (currentScroll + window.innerHeight / 2 >= getSteps().scrollSteps[i] + && i === getSteps().scrollSteps.length - 1) + ) { + return(i); } } } + function getCurrentPartFromCursor(cursorTop) { + for (let i = 0; i < getSteps().tlElSteps.length; i++) { + if (cursorTop - tlContainer.offsetTop >= getSteps().tlElSteps[i] && cursorTop - tlContainer.offsetTop < getSteps().tlElSteps[i + 1]) { + return(i); + } else if (cursorTop - tlContainer.offsetTop > getSteps().tlElSteps[getSteps().tlElSteps.length - 1]) { + return(getSteps().tlElSteps.length - 1); + } + } + } + function getCurrentTime(titleEl) { - let nextRow = titleEl.nextElementSibling; + let nextRow = titleEl?.nextElementSibling; while(nextRow) { if (nextRow.offsetTop > window.scrollY && nextRow.classList.contains('isContentPart')) {