Reveal photos on scroll on Location page
This commit is contained in:
@@ -27,7 +27,10 @@
|
|||||||
const hasIllustration = location.illustration_desktop && location.illustration_desktop_2x && location.illustration_mobile
|
const hasIllustration = location.illustration_desktop && location.illustration_desktop_2x && location.illustration_mobile
|
||||||
|
|
||||||
let introEl: HTMLElement
|
let introEl: HTMLElement
|
||||||
|
let photosListEl: HTMLElement
|
||||||
let scrollY: number
|
let scrollY: number
|
||||||
|
let observerPhotos: IntersectionObserver
|
||||||
|
let mutationPhotos: MutationObserver
|
||||||
let currentPage = 1
|
let currentPage = 1
|
||||||
let ended: boolean
|
let ended: boolean
|
||||||
let currentPhotosAmount: number
|
let currentPhotosAmount: number
|
||||||
@@ -138,6 +141,45 @@
|
|||||||
translateY: ['10%', 0],
|
translateY: ['10%', 0],
|
||||||
opacity: [0, 1],
|
opacity: [0, 1],
|
||||||
}, 900 + ($navigating ? DURATION.PAGE_IN : 0))
|
}, 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()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -220,7 +262,7 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
{#if photos.length}
|
{#if photos.length}
|
||||||
<section class="location-page__houses grid">
|
<section class="location-page__houses grid" bind:this={photosListEl}>
|
||||||
{#each photos as { title, image: { id, title: alt }, slug, city, date_taken }, index}
|
{#each photos as { title, image: { id, title: alt }, slug, city, date_taken }, index}
|
||||||
<div class="house grid">
|
<div class="house grid">
|
||||||
<div class="house__info">
|
<div class="house__info">
|
||||||
|
|||||||
@@ -244,16 +244,16 @@
|
|||||||
isIntersecting && observerPhotos.unobserve(target)
|
isIntersecting && observerPhotos.unobserve(target)
|
||||||
})
|
})
|
||||||
}, {
|
}, {
|
||||||
threshold: 0,
|
threshold: 0.3,
|
||||||
rootMargin: '0px 0px 0px'
|
rootMargin: '0px 0px 0px'
|
||||||
})
|
})
|
||||||
|
|
||||||
// Photos MutationObserver
|
// Photos MutationObserver
|
||||||
mutationPhotos = new MutationObserver((mutationsList, observer) => {
|
mutationPhotos = new MutationObserver((mutationsList, observer) => {
|
||||||
// Use traditional 'for loops' for IE 11
|
|
||||||
for (const mutation of mutationsList) {
|
for (const mutation of mutationsList) {
|
||||||
|
// When adding new childs
|
||||||
if (mutation.type === 'childList') {
|
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))
|
mutation.addedNodes.forEach((item: HTMLElement) => observerPhotos.observe(item))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,9 +13,11 @@
|
|||||||
|
|
||||||
// Information
|
// Information
|
||||||
&__info {
|
&__info {
|
||||||
|
--delay: 0.2s;
|
||||||
grid-column: 1 / span var(--columns);
|
grid-column: 1 / span var(--columns);
|
||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
@include bp (mob-lg) {
|
@include bp (mob-lg) {
|
||||||
max-width: min(540px, 85vw);
|
max-width: min(540px, 85vw);
|
||||||
@@ -27,11 +29,20 @@
|
|||||||
max-width: 800px;
|
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 {
|
.info {
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
color: $color-lightgray;
|
color: $color-lightgray;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 1.2s var(--ease-quart);
|
||||||
|
transition-delay: var(--delay);
|
||||||
|
|
||||||
@include bp (sm) {
|
@include bp (sm) {
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
@@ -57,6 +68,8 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
grid-column: 1 / span 17;
|
grid-column: 1 / span 17;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 2s var(--ease-quart);
|
||||||
|
|
||||||
@include bp (sm) {
|
@include bp (sm) {
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@@ -69,8 +82,40 @@
|
|||||||
img {
|
img {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: 100%;
|
||||||
object-fit: contain;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user