2024-06-11 03:55:34 -04:00
|
|
|
<!--
|
|
|
|
|
@component
|
|
|
|
|
A component that can be injected with a text to display it in a single line that clips if overflowing and intermittently scrolls
|
2024-07-18 22:52:08 -04:00
|
|
|
from one end to the other.
|
2024-06-11 03:55:34 -04:00
|
|
|
|
|
|
|
|
```tsx
|
|
|
|
|
<slot name="text" /> // An HTML element to wrap and style the text you want to scroll (e.g. div, spans, strongs)
|
|
|
|
|
```
|
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
<script lang="ts">
|
|
|
|
|
let slidingText: HTMLElement
|
|
|
|
|
let slidingTextWidth: number, slidingTextWrapperWidth: number
|
|
|
|
|
let scrollDirection: 1 | -1 = 1
|
|
|
|
|
$: scrollDistance = slidingTextWidth - slidingTextWrapperWidth
|
|
|
|
|
$: if (slidingText && scrollDistance > 0) slidingText.style.animationDuration = `${scrollDistance / 40}s`
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<div bind:clientWidth={slidingTextWrapperWidth} class="relative h-full w-full overflow-clip">
|
|
|
|
|
<span
|
|
|
|
|
bind:this={slidingText}
|
|
|
|
|
bind:clientWidth={slidingTextWidth}
|
|
|
|
|
on:animationend={() => (scrollDirection *= -1)}
|
|
|
|
|
id="scrollingText"
|
|
|
|
|
class="{scrollDistance > 0 ? (scrollDirection > 0 ? 'scrollLeft' : 'scrollRight') : ''} absolute whitespace-nowrap"
|
|
|
|
|
>
|
|
|
|
|
<slot name="text" />
|
|
|
|
|
</span>
|
2024-07-18 22:52:08 -04:00
|
|
|
<!-- This is so the wrapper can calculate how big it should be based on the text -->
|
|
|
|
|
<span class="pointer-events-none line-clamp-1 opacity-0">
|
|
|
|
|
<slot name="text" />
|
|
|
|
|
</span>
|
2024-06-11 03:55:34 -04:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
#scrollingText {
|
|
|
|
|
animation-timing-function: linear;
|
|
|
|
|
animation-fill-mode: both;
|
|
|
|
|
animation-delay: 10s;
|
|
|
|
|
}
|
|
|
|
|
#scrollingText:hover {
|
|
|
|
|
animation-play-state: paused;
|
|
|
|
|
}
|
|
|
|
|
.scrollLeft {
|
|
|
|
|
animation-name: scrollLeft;
|
|
|
|
|
}
|
|
|
|
|
.scrollRight {
|
|
|
|
|
animation-name: scrollRight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes scrollLeft {
|
|
|
|
|
0% {
|
|
|
|
|
left: 0%;
|
|
|
|
|
transform: translateX(0%);
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
left: 100%;
|
|
|
|
|
transform: translateX(-100%);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes scrollRight {
|
|
|
|
|
0% {
|
|
|
|
|
left: 100%;
|
|
|
|
|
transform: translateX(-100%);
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
left: 0%;
|
|
|
|
|
transform: translateX(0%);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|