67 lines
1.6 KiB
Plaintext
67 lines
1.6 KiB
Plaintext
---
|
|
interface Props {
|
|
className?: string;
|
|
delay?: number;
|
|
direction?: "up" | "down" | "left" | "right";
|
|
distance?: number;
|
|
}
|
|
|
|
const { className = "", delay = 0, direction = "up", distance = 20 } = Astro.props;
|
|
|
|
const directionMap = {
|
|
up: { x: 0, y: distance },
|
|
down: { x: 0, y: -distance },
|
|
left: { x: distance, y: 0 },
|
|
right: { x: -distance, y: 0 },
|
|
};
|
|
|
|
const { x, y } = directionMap[direction];
|
|
const uniqueId = `fade-in-${Math.random().toString(36).substring(2, 9)}`;
|
|
---
|
|
|
|
<div id={uniqueId} class={`fade-in ${className}`} data-delay={delay} data-direction={direction}>
|
|
<slot />
|
|
</div>
|
|
|
|
<style>
|
|
.fade-in {
|
|
opacity: 0;
|
|
transform: translate(var(--start-x, 0px), var(--start-y, 20px));
|
|
transition:
|
|
opacity 0.6s ease-out,
|
|
transform 0.6s ease-out;
|
|
}
|
|
|
|
.fade-in.visible {
|
|
opacity: 1;
|
|
transform: translate(0px, 0px);
|
|
}
|
|
</style>
|
|
|
|
<script define:vars={{ uniqueId, x, y, delay }}>
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
const element = document.getElementById(uniqueId);
|
|
if (element) {
|
|
element.style.setProperty("--start-x", `${x}px`);
|
|
element.style.setProperty("--start-y", `${y}px`);
|
|
|
|
const observer = new IntersectionObserver(
|
|
(entries) => {
|
|
entries.forEach((entry) => {
|
|
if (entry.isIntersecting) {
|
|
setTimeout(() => {
|
|
element.classList.add("visible");
|
|
}, delay * 1000);
|
|
|
|
observer.disconnect();
|
|
}
|
|
});
|
|
},
|
|
{ threshold: 0.1, rootMargin: "0px 0px -10% 0px" }
|
|
);
|
|
|
|
observer.observe(element);
|
|
}
|
|
});
|
|
</script>
|