aboutsummaryrefslogtreecommitdiff
path: root/src/lib/Lazy.svelte
blob: 8bb180ac0695fe0e26aea40dc6f66a65ea1347bd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<script lang="ts">
	import { onMount, onDestroy } from 'svelte';

	export let top = 0;
	export let bottom = 0;
	export let left = 0;
	export let right = 0;
	export let steps = 100;
	export let threshold = 0.01;
	export let once = false;

	let element: Element;
	let percent: number = 0;
	let visible = false;
	let observer: IntersectionObserver;

	const intersectPercent = (
		entries: IntersectionObserverEntry[],
		observer: IntersectionObserver
	) => {
		for (let entry of entries)
			if (entry.target === element) {
				percent = Math.round(entry.intersectionRatio * 100);
				visible = entry.intersectionRatio >= threshold;

				if (visible && once) observer.unobserve(element);

				break;
			}
	};

	onMount(() => {
		if ('IntersectionObserver' in window) {
			let options = {
				rootMargin: `${top}px ${right}px ${bottom}px ${left}px`,
				threshold: Array.from({ length: steps }, (_, i) => i / (steps - 1))
			};

			observer = new IntersectionObserver(intersectPercent, options);
			observer.observe(element);
		}
	});

	onDestroy(() => observer?.unobserve(element));
</script>

<div bind:this={element}>
	<slot {visible} {percent} />
</div>