From fd871d55f9fae874abd5c5ee61b9a35e12d797c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fe=CC=81lix=20Pe=CC=81ault?= Date: Thu, 18 Nov 2021 22:06:29 +0100 Subject: [PATCH] Reveal photos on scroll on Location page --- src/routes/[country]/[location]/index.svelte | 44 +++++++++++++++++- src/routes/photos.svelte | 6 +-- src/style/organisms/_house.scss | 49 +++++++++++++++++++- 3 files changed, 93 insertions(+), 6 deletions(-) diff --git a/src/routes/[country]/[location]/index.svelte b/src/routes/[country]/[location]/index.svelte index d396954..dca910f 100644 --- a/src/routes/[country]/[location]/index.svelte +++ b/src/routes/[country]/[location]/index.svelte @@ -27,7 +27,10 @@ const hasIllustration = location.illustration_desktop && location.illustration_desktop_2x && location.illustration_mobile let introEl: HTMLElement + let photosListEl: HTMLElement let scrollY: number + let observerPhotos: IntersectionObserver + let mutationPhotos: MutationObserver let currentPage = 1 let ended: boolean let currentPhotosAmount: number @@ -138,6 +141,45 @@ translateY: ['10%', 0], opacity: [0, 1], }, 900 + ($navigating ? DURATION.PAGE_IN : 0)) + + + // Photos IntersectionObserver + observerPhotos = new IntersectionObserver(entries => { + entries.forEach(({ isIntersecting, target }: IntersectionObserverEntry) => { + target.classList.toggle('is-visible', isIntersecting) + + // Run effect once + isIntersecting && observerPhotos.unobserve(target) + }) + }, { + threshold: 0.3, + rootMargin: '0px 0px 0px' + }) + + // Photos MutationObserver + mutationPhotos = new MutationObserver((mutationsList, observer) => { + // When adding new childs + for (const mutation of mutationsList) { + if (mutation.type === 'childList') { + // Observe new items + mutation.addedNodes.forEach((item: HTMLElement) => observerPhotos.observe(item)) + } + } + }) + mutationPhotos.observe(photosListEl, { + childList: true, + }) + + // Observe existing elements + const existingPhotos = photosListEl.querySelectorAll('.house') + existingPhotos.forEach(el => observerPhotos.observe(el)) + + + // Destroy + return () => { + observerPhotos && observerPhotos.disconnect() + mutationPhotos && mutationPhotos.disconnect() + } }) @@ -220,7 +262,7 @@ {#if photos.length} -
+
{#each photos as { title, image: { id, title: alt }, slug, city, date_taken }, index}
diff --git a/src/routes/photos.svelte b/src/routes/photos.svelte index e3b4346..272d100 100644 --- a/src/routes/photos.svelte +++ b/src/routes/photos.svelte @@ -244,16 +244,16 @@ isIntersecting && observerPhotos.unobserve(target) }) }, { - threshold: 0, + threshold: 0.3, rootMargin: '0px 0px 0px' }) // Photos MutationObserver mutationPhotos = new MutationObserver((mutationsList, observer) => { - // Use traditional 'for loops' for IE 11 for (const mutation of mutationsList) { + // When adding new childs if (mutation.type === 'childList') { - console.log('A child node has been added or removed.') + // Observe new items mutation.addedNodes.forEach((item: HTMLElement) => observerPhotos.observe(item)) } } diff --git a/src/style/organisms/_house.scss b/src/style/organisms/_house.scss index 8464cdc..19490a1 100644 --- a/src/style/organisms/_house.scss +++ b/src/style/organisms/_house.scss @@ -13,9 +13,11 @@ // Information &__info { + --delay: 0.2s; grid-column: 1 / span var(--columns); margin-bottom: 32px; padding: 0 20px; + overflow: hidden; @include bp (mob-lg) { max-width: min(540px, 85vw); @@ -27,11 +29,20 @@ max-width: 800px; } + h2 { + opacity: 0; + transform: translate3d(0, 25%, 0); + transition: transform 1.2s var(--ease-quart), opacity 1.2s var(--ease-quart); + transition-delay: var(--delay); + } .info { display: block; margin-top: 16px; color: $color-lightgray; line-height: 1.5; + opacity: 0; + transition: opacity 1.2s var(--ease-quart); + transition-delay: var(--delay); @include bp (sm) { margin-top: 24px; @@ -57,6 +68,8 @@ position: relative; display: block; grid-column: 1 / span 17; + opacity: 0; + transition: opacity 2s var(--ease-quart); @include bp (sm) { border-radius: 8px; @@ -69,8 +82,40 @@ img { display: block; width: 100%; - height: auto; - object-fit: contain; + height: 100%; + object-fit: cover; + transform: scale3d(1.125, 1.125, 1.125); + transition: transform 2s var(--ease-quart), opacity 1.2s var(--ease-quart); + will-change: transform; + } + + // Scale down image on hover + a:hover { + img { + opacity: 0.6; + transform: scale3d(1.03, 1.03, 1.03) !important; + transition-duration: 1.2s; + } + } + } + + // Visible state + &.is-visible { + .house__info { + h2 { + opacity: 1; + transform: translate3d(0,0,0); + } + .info { + opacity: 1; + } + } + .house__photo { + opacity: 1; + + img { + transform: scale3d(1,1,1); + } } }