From 22967b6f5cb87220cd66d8cd8a52f51337944d36 Mon Sep 17 00:00:00 2001 From: Spedon Date: Sat, 11 Mar 2023 19:56:27 +0800 Subject: [PATCH] finish transition to json data fetching add smooth close animation --- assets/css/_partial/_image.scss | 93 ++++++++++++++++----- assets/js/theme.js | 143 ++++++++++++++++++++------------ layouts/index.html | 10 ++- 3 files changed, 170 insertions(+), 76 deletions(-) diff --git a/assets/css/_partial/_image.scss b/assets/css/_partial/_image.scss index 86befda..0971973 100644 --- a/assets/css/_partial/_image.scss +++ b/assets/css/_partial/_image.scss @@ -1,25 +1,22 @@ .image_container { max-height: 55vmin; position: absolute; + width: auto; + max-width: 100vw; transform: translate(-50%, -50%); + opacity: 1; + display: flex; + align-items: center; img { max-height: 55vmin; + max-width: 100vw; + object-fit: contain; width: auto; } } -.image_container[data-status="inactive"] { - opacity: 0; - transition: opacity 300ms ease-in-out; -} - -.image_container[data-status="active"] { - opacity: 1; - transition: opacity 0ms ease-in-out; -} - -.top { +.image_container[data-status='t0'] { transition: all 0.5s ease-in-out 1.5s; max-height: calc(100vh - var(--footer-height)); width: auto; @@ -36,19 +33,77 @@ } } -.trailingImage1 { - transition: opacity 0.5s ease-in-out 1s; +.image_container[data-status='t1'] { + transition: opacity 0.5s ease-out 1s; opacity: 0; } -.trailingImage2 { - transition: opacity 0.5s ease-in-out 0.75s; +.image_container[data-status='t2'] { + transition: opacity 0.5s ease-out 0.75s; opacity: 0; } -.trailingImage3 { - transition: opacity 0.5s ease-in-out 0.5s; +.image_container[data-status='t3'] { + transition: opacity 0.5s ease-out 0.5s; opacity: 0; } -.trailingImage4 { - transition: opacity 0.5s ease-in-out 0.25s; +.image_container[data-status='t4'] { + transition: opacity 0.5s ease-out 0.25s; opacity: 0; +} + +.image_container[data-status='r0'] { + transition: all 0.5s ease-in-out 1s; + max-height: 55vmin; + position: absolute; + transform: translate(-50%, -50%); + opacity: 1; + width: auto; + max-width: 100vw; + display: flex; + align-items: center; + + img { + transition: all 1s ease-in-out 0s; + max-height: 55vmin; + max-width: 100vw; + object-fit: contain; + width: auto; + } +} + +.image_container[data-status='r1'] { + transition: opacity 0.25s ease-out 1.5s; + opacity: 1; +} +.image_container[data-status='r2'] { + transition: opacity 0.25s ease-out 1.75s; + opacity: 1; +} +.image_container[data-status='r3'] { + transition: opacity 0.25s ease-out 2s; + opacity: 1; +} +.image_container[data-status='r4'] { + transition: opacity 0.25s ease-out 2.25s; + opacity: 1; +} + + +#layer5 { + z-index: 5; +} + +#layer4 { + z-index: 4; +} + +#layer3 { + z-index: 3; +} + +#layer2 { + z-index: 2; +} + +#layer1 { + z-index: 1; } \ No newline at end of file diff --git a/assets/js/theme.js b/assets/js/theme.js index 2f2c723..85703be 100644 --- a/assets/js/theme.js +++ b/assets/js/theme.js @@ -1,8 +1,11 @@ -const images = document.getElementsByClassName('image_container') +const imagesArray = JSON.parse(document.getElementById('images_array').textContent).sort((a, b) => { + if (a.index < b.index) { + return -1 + } + return 1 +}) -const imagesArray = JSON.parse(document.getElementById('images_array').textContent) - -alert(imagesArray.length) +const imagesArrayLen = imagesArray.length const thresholdNum = document.getElementsByClassName('thid') @@ -12,7 +15,15 @@ const thresholdSensitivity = [100, 40, 18, 14, 9, 5] const r = document.querySelector(':root') -const activeImageIndexes = [] +const posXArray = ['0px', '0px', '0px', '0px', '0px'] + +const posYArray = ['0px', '0px', '0px', '0px', '0px'] + +const layer5 = document.getElementById('layer5') +const layer4 = document.getElementById('layer4') +const layer3 = document.getElementById('layer3') +const layer2 = document.getElementById('layer2') +const layer1 = document.getElementById('layer1') let thresholdIndex = 2 @@ -20,6 +31,10 @@ let globalIndex = 0 let last = { x: 0, y: 0 } +function sleep (ms) { + return new Promise(resolve => setTimeout(resolve, ms)) +} + // fulfill space with zero function duper (num) { return ('0000' + num).slice(-4) @@ -43,9 +58,9 @@ function overlayInit () { document.getElementsByClassName('overlay').item(0).style.zIndex = '7' } -// footer index number display module -const footerIndex = document.getElementsByClassName('ftid') const numSpan = (numOne, numTwo) => { + // footer index number display module + const footerIndex = document.getElementsByClassName('ftid') const numOneString = duper(numOne) const numTwoString = duper(numTwo) for (let i = 0; i <= 7; i++) { @@ -59,9 +74,10 @@ const numSpan = (numOne, numTwo) => { // initialization function init () { - numSpan(0, images.length) + numSpan(0, imagesArrayLen) thresholdUpdate() footerHeightUpdate() + // threshold buttons initialization document.getElementById('thresholdDec').addEventListener('click', function () { if (thresholdIndex > 0) { thresholdIndex-- @@ -92,41 +108,61 @@ const overlayCursor = e => { overlayCursor.style.top = `${e.clientY}px` } -// let specified image show -const activate = (image, x, y) => { - // top reset - Array.from(document.getElementsByClassName('top')).forEach(e => { - e.classList.remove('top') - e.replaceWith(e.cloneNode(true)) - }) - // z index reset - image.style.left = `${x}px` - image.style.top = `${y}px` - // activate image - image.dataset.status = 'active' - - activeImageIndexes.push(globalIndex % images.length) - if (activeImageIndexes.length > 5) { - images[activeImageIndexes.shift()].style.zIndex = '-1' +const FIFO = element => { + function layerProcess (layerL, layerH) { + if (layerL.childElementCount) layerL.removeChild(layerL.lastElementChild) + if (layerH.childElementCount) layerL.appendChild(layerH.lastElementChild.cloneNode(true)) } - activeImageIndexes.forEach((e, i) => { - images[e].style.zIndex = `${i + 1}` - }) + layerProcess(layer1, layer2) + layerProcess(layer2, layer3) + layerProcess(layer3, layer4) + layerProcess(layer4, layer5) + if (layer5.childElementCount) layer5.removeChild(layer5.lastElementChild) + layer5.appendChild(element) +} + +const posCache = (x, y) => { + // pop element if length surpass limitation + posXArray.shift() + posYArray.shift() + // push new element + posXArray.push(`${x}px`) + posYArray.push(`${y}px`) +} + +function layersPosSet () { + function posSet (layer, index) { + layer.style.left = posXArray[index] + layer.style.top = posYArray[index] + } + posSet(layer5, 4) + posSet(layer4, 3) + posSet(layer3, 2) + posSet(layer2, 1) + posSet(layer1, 0) +} + +// let specified image show +const activate = (index, x, y) => { + const img = document.createElement('img') + img.setAttribute('src', imagesArray[index].url) + img.setAttribute('alt', imagesArray[index].index) + img.setAttribute('height', imagesArray[index].height) + img.setAttribute('width', imagesArray[index].width) + posCache(x, y) + layersPosSet() + FIFO(img) // top - image.addEventListener('click', () => { + layer5.addEventListener('click', () => { // stop images animation window.removeEventListener('mousemove', handleOnMove) // set top image - image.classList.add('top') - center(image) - // set tailing images - activeImageIndexes.forEach((e, i) => { - const activeImageNum = activeImageIndexes.length - if (i < 4) { - images[e].classList.add(`trailingImage${activeImageNum - 1 - i}`) - } - images[e].classList.replace('active', 'resume') - }) + center(layer5) + layer5.dataset.status = 't0' + layer4.dataset.status = 't1' + layer3.dataset.status = 't2' + layer2.dataset.status = 't3' + layer1.dataset.status = 't4' // overlay init overlayInit() window.addEventListener('mousemove', overlayCursor) @@ -147,16 +183,10 @@ const distanceFromLast = (x, y) => { const handleOnMove = e => { if (distanceFromLast(e.clientX, e.clientY) > (window.innerWidth / thresholdSensitivity[thresholdIndex])) { // images showing array - const imageIndex = globalIndex % images.length - const lead = images[imageIndex] - const tail = images[(globalIndex - 5) % images.length] + const imageIndex = globalIndex % imagesArrayLen // show top image and change index - activate(lead, e.clientX, e.clientY) - numSpan((imageIndex + 1), images.length) - // hide the image unused - if (tail) { - tail.dataset.status = 'inactive' - } + activate(imageIndex, e.clientX, e.clientY) + numSpan((imageIndex + 1), imagesArrayLen) // self increment globalIndex++ } @@ -177,13 +207,20 @@ document.getElementsByClassName('prev_section').item(0).addEventListener('mouseo document.getElementsByClassName('overlay_cursor').item(0).innerText = 'PREV' }) -document.getElementsByClassName('close_section').item(0).addEventListener('click', () => { +document.getElementsByClassName('close_section').item(0).addEventListener('click', async function f () { document.getElementsByClassName('overlay').item(0).style.zIndex = '-1' - document.getElementsByClassName('top').item(0).classList.remove('top') - document.getElementsByClassName('trailingImage4').item(0).classList.remove('trailingImage4') - document.getElementsByClassName('trailingImage3').item(0).classList.remove('trailingImage3') - document.getElementsByClassName('trailingImage2').item(0).classList.remove('trailingImage2') - document.getElementsByClassName('trailingImage1').item(0).classList.remove('trailingImage1') + layersPosSet() + layer5.dataset.status = 'r0' + layer4.dataset.status = 'r1' + layer3.dataset.status = 'r2' + layer2.dataset.status = 'r3' + layer1.dataset.status = 'r4' + await sleep(2500) + layer5.dataset.status = 'null' + layer4.dataset.status = 'null' + layer3.dataset.status = 'null' + layer2.dataset.status = 'null' + layer1.dataset.status = 'null' window.addEventListener('mousemove', handleOnMove) }) diff --git a/layouts/index.html b/layouts/index.html index 52e88ff..7a16907 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -24,13 +24,15 @@ {{ $.Scratch.Add "img" slice }} {{ range . }} {{ $index = sub $index 1}} - {{ $.Scratch.Add "img" (dict "link" .RelPermalink "height" .Height "width" .Width) }} -
- -
+ {{ $.Scratch.Add "img" (dict "index" (string $index) "url" (string .RelPermalink) "height" (string .Height) "width" (string .Width)) }} {{ end }} {{ end }} +
+
+
+
+