Open
Description
<div
transition:persist
id="astro-loading-indicator"
class="astro-loading-indicator"
>
</div>
<style>
.astro-loading-indicator {
--progress: 0;
--animation-duration: 300ms;
--opacity-animation-duration: 150ms;
pointer-events: none;
background-color: hsl(192, 41%, 84%);
position: fixed;
z-index: 1031;
top: 0;
left: 0;
width: 100%;
height: 3px;
transition:
transform var(--animation-duration) ease-out,
opacity var(--opacity-animation-duration)
var(--opacity-animation-duration) ease-in;
transform: translate3d(0, 0, 0) scaleX(var(--progress, 0));
transform-origin: 0;
}
</style>
<script>
(() => {
// This is the initial interval
let animationDuration = 50;
let progress = 0.25;
let opacity = 0;
let trickleInterval: number | undefined = undefined;
let preparationTimestamp: number = 0;
const element = document.getElementById("astro-loading-indicator");
/** @param {typeof progress} _progress */
const setProgress = (_progress: number) => {
progress = _progress;
element?.style.setProperty("--progress", String(progress));
};
/** @param {typeof opacity} _opacity */
const setOpacity = (_opacity: number) => {
opacity = _opacity;
element?.style.setProperty("opacity", String(opacity));
};
const setAnimationDuration = (duration: number) => {
animationDuration = duration;
let styleAnimationDuration = Math.min(300, animationDuration);
element?.style.setProperty(
"--animation-duration",
`${styleAnimationDuration}ms`,
);
element?.style.setProperty(
"--opacity-animation-duration",
`${styleAnimationDuration / 2}ms`,
);
return styleAnimationDuration;
};
setOpacity(opacity);
document.addEventListener("astro:before-preparation", () => {
preparationTimestamp = performance.now();
setOpacity(1);
trickleInterval = window.setInterval(() => {
setProgress(progress + Math.random() * 0.05);
}, animationDuration * 0.05);
});
document.addEventListener("astro:before-swap", (ev) => {
let computedDuration = performance.now() - preparationTimestamp;
var styleAnimationDuration = setAnimationDuration(computedDuration);
window.clearInterval(trickleInterval);
trickleInterval = undefined;
setProgress(1);
window.setTimeout(() => {
setOpacity(0);
}, styleAnimationDuration / 2);
window.setTimeout(() => {
setProgress(0.25);
}, styleAnimationDuration * 1.5);
});
})();
</script>
Metadata
Metadata
Assignees
Labels
No labels