fixes rootmargin and scroll event triggers
This commit is contained in:
parent
ef76d67252
commit
6858a8a868
2 changed files with 41 additions and 45 deletions
|
|
@ -45,8 +45,24 @@
|
|||
}: Props = $props();
|
||||
|
||||
let visible = $state(false);
|
||||
let visibleOnce = $state(false);
|
||||
let container: HTMLElement | undefined = $state(undefined);
|
||||
|
||||
function scrollHandler() {
|
||||
// Only trigger if `visibleOnce` is false
|
||||
if (container && !visibleOnce) {
|
||||
const bcr = container.getBoundingClientRect();
|
||||
visible =
|
||||
bcr.bottom + bottom > 0 &&
|
||||
bcr.right + right > 0 &&
|
||||
bcr.top - top < window.innerHeight &&
|
||||
bcr.left - left < window.innerWidth;
|
||||
|
||||
// If `once` is true, set `visibleOnce` to true once `visible` becomes true
|
||||
if (once && visible) visibleOnce = true;
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
if (typeof IntersectionObserver !== 'undefined') {
|
||||
const rootMargin = `${top}px ${right}px ${bottom}px ${left}px`;
|
||||
|
|
@ -63,31 +79,24 @@
|
|||
threshold,
|
||||
}
|
||||
);
|
||||
|
||||
if (container) observer.observe(container);
|
||||
// Unobserve when the component is unmounted
|
||||
return () => {
|
||||
if (container) observer.unobserve(container);
|
||||
};
|
||||
}
|
||||
function handler() {
|
||||
if (container) {
|
||||
const bcr = container.getBoundingClientRect();
|
||||
|
||||
visible =
|
||||
bcr.bottom + bottom > 0 &&
|
||||
bcr.right + right > 0 &&
|
||||
bcr.top - top < window.innerHeight &&
|
||||
bcr.left - left < window.innerWidth;
|
||||
}
|
||||
if (visible && once) {
|
||||
window.removeEventListener('scroll', handler);
|
||||
}
|
||||
}
|
||||
window.addEventListener('scroll', handler);
|
||||
return () => window.removeEventListener('scroll', handler);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="visibility-tracker" bind:this={container}>
|
||||
<svelte:window onscroll={scrollHandler} />
|
||||
|
||||
<div
|
||||
class="visibility-tracker"
|
||||
class:visible
|
||||
class:not-visible={!visible}
|
||||
bind:this={container}
|
||||
>
|
||||
{#if children}
|
||||
{@render children(visible)}
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -5,24 +5,28 @@
|
|||
import FeaturePhoto from '../../FeaturePhoto/FeaturePhoto.svelte';
|
||||
import sharkSrc from '../../FeaturePhoto/images/shark.jpg';
|
||||
|
||||
let top = 200;
|
||||
|
||||
const demoText =
|
||||
"Adjust the window dimension to see what happens when `<div class='visibility-tracker'>` comes into <a href='https://codepen.io/michellebarker/full/xxwLpRG'>Internsection Observer's</a> view.";
|
||||
'Take a look at the *Elements* tab in Inspector to see how the photo in the middle of the page appears in the DOM only when its container comes into view.';
|
||||
|
||||
let demoText2 = $derived(
|
||||
`The top value for \`rootMargin\` is set to \`${top}px\` in this demo. Read about how \`rootMargin\` affects the <a href='https://codepen.io/michellebarker/full/xxwLpRG'>Intersection Observer's behaviour here</a>.`
|
||||
);
|
||||
|
||||
const text =
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';
|
||||
|
||||
let top = 500;
|
||||
</script>
|
||||
|
||||
<BodyText text={`**${demoText}**`} />
|
||||
|
||||
<BodyText text={`**${demoText2}**`} />
|
||||
<BodyText {text} />
|
||||
<BodyText {text} />
|
||||
<BodyText {text} />
|
||||
<BodyText {text} />
|
||||
|
||||
<!-- <div class="root-margin-demo" style="padding-top:{top}px;">
|
||||
<p class="margin-value font-note font-medium">Root margin top: {top}px</p>
|
||||
</div> -->
|
||||
<Visible {top}>
|
||||
<Visible {top} once={false}>
|
||||
{#snippet children(visible)}
|
||||
{#if visible}
|
||||
<FeaturePhoto
|
||||
|
|
@ -31,29 +35,12 @@
|
|||
caption="Carcharodon carcharias - REUTERS"
|
||||
/>
|
||||
{:else}
|
||||
<Block>
|
||||
<h2 class="not-visible">Not yet visible.</h2>
|
||||
</Block>
|
||||
<Block><h2>Not yet visible.</h2></Block>
|
||||
{/if}
|
||||
{/snippet}
|
||||
</Visible>
|
||||
<BodyText {text} />
|
||||
<BodyText {text} />
|
||||
|
||||
<style lang="scss">
|
||||
@use '../../../scss/mixins' as mixins;
|
||||
|
||||
.root-margin-demo {
|
||||
position: relative;
|
||||
background: lightblue;
|
||||
margin: auto;
|
||||
max-width: mixins.$column-width-normal;
|
||||
|
||||
p.margin-value {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<BodyText {text} />
|
||||
<BodyText {text} />
|
||||
<BodyText {text} />
|
||||
|
|
|
|||
Loading…
Reference in a new issue