infinite scroll marquee almost done
This commit is contained in:
parent
3d615c4b5f
commit
eca995ca2c
7 changed files with 136 additions and 77 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
import matrixLogo from "@icons/matrix-logo.svg?raw";
|
import matrixLogo from "@icons/matrix-logo.svg?raw";
|
||||||
import discordLogo from "@icons/discord-logo.svg?raw";
|
import discordLogo from "@icons/discord-logo.svg?raw";
|
||||||
import gitLogo from "@icons/git-logo.svg?raw";
|
import gitLogo from "@icons/git-logo.svg?raw";
|
||||||
|
import { ThemeSelect } from "./hooks/ThemeSwitch";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
class?: string;
|
class?: string;
|
||||||
|
|
@ -18,6 +19,7 @@ const props = Astro.props;
|
||||||
and our contributors
|
and our contributors
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
<ThemeSelect client:load />
|
||||||
<div class="socials-changelog">
|
<div class="socials-changelog">
|
||||||
<section class="socials">
|
<section class="socials">
|
||||||
<a href="https://matrix.to/#/#quickshell:outfoxxed.me" target="_blank" aria-label="Join our matrix space">
|
<a href="https://matrix.to/#/#quickshell:outfoxxed.me" target="_blank" aria-label="Join our matrix space">
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import MarqueeContent from "./MarqueeContent.astro";
|
||||||
marquee.style.setProperty("--mult", "1")
|
marquee.style.setProperty("--mult", "1")
|
||||||
|
|
||||||
window.addEventListener("load", autoplayInit, false);
|
window.addEventListener("load", autoplayInit, false);
|
||||||
const videos = document.getElementsByClassName("marquee-item-content") as HTMLCollectionOf<HTMLVideoElement>;
|
let videos = document.getElementsByClassName("marquee-item-content") as HTMLCollectionOf<HTMLVideoElement>;
|
||||||
const videoCount = videos.length;
|
const videoCount = videos.length;
|
||||||
const lastVideoIndex = videos[videos.length - 1]
|
const lastVideoIndex = videos[videos.length - 1]
|
||||||
let currentVideoIndex = 0;
|
let currentVideoIndex = 0;
|
||||||
|
|
@ -38,6 +38,24 @@ import MarqueeContent from "./MarqueeContent.astro";
|
||||||
}
|
}
|
||||||
|
|
||||||
currentVideoIndex = index;
|
currentVideoIndex = index;
|
||||||
|
if (index === videos.length - 1) {
|
||||||
|
console.log("shift")
|
||||||
|
|
||||||
|
const shifted = videos.item(0);
|
||||||
|
marquee.firstElementChild.remove()
|
||||||
|
const video_div = document.createElement("div");
|
||||||
|
|
||||||
|
video_div.classList.add("marquee-item");
|
||||||
|
console.log("shift: ",video_div.classList.toString())
|
||||||
|
|
||||||
|
shifted.setAttribute("data-media-index", (index+1).toString())
|
||||||
|
|
||||||
|
video_div.appendChild(shifted);
|
||||||
|
marquee.appendChild(video_div);
|
||||||
|
videos = document.getElementsByClassName("marquee-item-content") as HTMLCollectionOf<HTMLVideoElement>;
|
||||||
|
currentVideoIndex = index - 1;
|
||||||
|
console.log("shift", marquee)
|
||||||
|
}
|
||||||
currentVideo = videos[currentVideoIndex];
|
currentVideo = videos[currentVideoIndex];
|
||||||
|
|
||||||
currentVideo.currentTime = 0;
|
currentVideo.currentTime = 0;
|
||||||
|
|
@ -47,8 +65,8 @@ import MarqueeContent from "./MarqueeContent.astro";
|
||||||
|
|
||||||
function offsetCarousel(offset: number) {
|
function offsetCarousel(offset: number) {
|
||||||
let nextIndex = currentVideoIndex + offset;
|
let nextIndex = currentVideoIndex + offset;
|
||||||
if (nextIndex < 0) nextIndex += videoCount;
|
// if (nextIndex < 0) nextIndex += videoCount;
|
||||||
nextIndex = nextIndex % videoCount;
|
// nextIndex = nextIndex % videoCount;
|
||||||
setActiveVideo(nextIndex);
|
setActiveVideo(nextIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,6 +75,7 @@ import MarqueeContent from "./MarqueeContent.astro";
|
||||||
rootMargin: "0px",
|
rootMargin: "0px",
|
||||||
threshold: 0.1,
|
threshold: 0.1,
|
||||||
};
|
};
|
||||||
|
const mult = marquee.style.getPropertyValue("--mult") ?? 0;
|
||||||
|
|
||||||
const observer = new IntersectionObserver((entries) => {
|
const observer = new IntersectionObserver((entries) => {
|
||||||
entries.forEach((entry) => {
|
entries.forEach((entry) => {
|
||||||
|
|
@ -86,28 +105,8 @@ import MarqueeContent from "./MarqueeContent.astro";
|
||||||
video.style.animationPlayState = "running";
|
video.style.animationPlayState = "running";
|
||||||
video.style.animationDirection = "normal";
|
video.style.animationDirection = "normal";
|
||||||
}
|
}
|
||||||
if (entry.isIntersecting && video === lastVideoIndex) {
|
|
||||||
addNextVideo();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}, intersectionOptions);
|
}, intersectionOptions);
|
||||||
function addNextVideo() {
|
|
||||||
const firstVideo = videos[0];
|
|
||||||
if (!firstVideo) return;
|
|
||||||
|
|
||||||
const newVideo = firstVideo.cloneNode(true) as HTMLVideoElement;
|
|
||||||
|
|
||||||
// IMPORTANT: Reset the state of the new video
|
|
||||||
newVideo.pause();
|
|
||||||
newVideo.currentTime = 0;
|
|
||||||
newVideo.style.animationName = "none"; // Reset any lingering animation styles
|
|
||||||
|
|
||||||
// append to the marquee
|
|
||||||
marquee.appendChild(newVideo);
|
|
||||||
|
|
||||||
// observe the new video
|
|
||||||
observer.observe(newVideo);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const video of videos) {
|
for (const video of videos) {
|
||||||
observer.observe(video);
|
observer.observe(video);
|
||||||
|
|
|
||||||
|
|
@ -35,24 +35,26 @@ const videos = [
|
||||||
];
|
];
|
||||||
---
|
---
|
||||||
<div id="marquee-content" class="marquee-content" data-scroll="0" data-media-index="0">
|
<div id="marquee-content" class="marquee-content" data-scroll="0" data-media-index="0">
|
||||||
{videos.map(({ author, source, installable, path }, index) =>
|
{videos.map(({ author, source, installable, path }, index) => {
|
||||||
<div class="marquee-item">
|
return (
|
||||||
<video
|
<div class=`marquee-item`>
|
||||||
data-media-index={index}
|
<video
|
||||||
data-media-author={author}
|
data-media-index={index}
|
||||||
id="showcase-video"
|
data-media-author={author}
|
||||||
class="marquee-item-spacing marquee-item-content"
|
id="showcase-video"
|
||||||
muted
|
class="marquee-item-spacing marquee-item-content"
|
||||||
controls
|
muted
|
||||||
playsinline
|
controls
|
||||||
preload="metadata"
|
playsinline
|
||||||
>
|
preload="metadata"
|
||||||
<source src={path} type="video/mp4"/>
|
>
|
||||||
|
<source src={path} type="video/mp4"/>
|
||||||
</video>
|
</video>
|
||||||
<p>
|
<p>
|
||||||
Configuration by <Fragment set:html={author}/>
|
Configuration by <Fragment set:html={author}/>
|
||||||
{source && !installable && <>(<a href={source}>source code</a>)</>}
|
{source && !installable && <>(<a href={source}>source code</a>)</>}
|
||||||
{source && installable && <>(<a href={source}>install</a>)</>}
|
{source && installable && <>(<a href={source}>install</a>)</>}
|
||||||
</p>
|
</p>
|
||||||
</div>)}
|
</div>
|
||||||
|
)})}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -138,15 +138,20 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes bounce {
|
@keyframes bounce {
|
||||||
0%,
|
0% {
|
||||||
100% {
|
transform: none;
|
||||||
transform: translateY(-25%);
|
animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
||||||
animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
transform: none;
|
transform: translateY(-12%);
|
||||||
animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
color: hsla(var(--green) 100 69 / 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: none;
|
||||||
|
animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,5 +171,6 @@
|
||||||
--animate-spin: spin 1s linear infinite;
|
--animate-spin: spin 1s linear infinite;
|
||||||
--animate-ping: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
|
--animate-ping: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
|
||||||
--animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
--animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||||
--animate-bounce: bounce 1s infinite;
|
--animate-bounce: bounce 0.6s var(--ease-out) forwards;
|
||||||
|
--animate-fade: fade 0.3s cubic-bezier(0.4, 0, 0.6, 1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ html {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
transition: all 0.3s var(--ease-in-out);
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
pre.shiki {
|
pre.shiki {
|
||||||
margin-block: 1.618rem;
|
margin-block: var(--lg);
|
||||||
}
|
}
|
||||||
|
|
||||||
:where(p, li):has(> code) code {
|
:where(p, li):has(> code) code {
|
||||||
padding-inline: 0.272rem;
|
padding-inline: var(--2xl);
|
||||||
border-radius: 0.272rem;
|
border-radius: var(--2xl);
|
||||||
color: hsl(var(--blue) 100% 69%);
|
color: hsl(var(--blue) 100 69);
|
||||||
background-color: hsl(var(--blue) 85% 35% / 0.1);
|
background-color: hsla(var(--blue) 85 35 / 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.shiki,
|
.shiki,
|
||||||
|
|
@ -26,6 +26,9 @@ pre {
|
||||||
border-radius: 0.618rem;
|
border-radius: 0.618rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-wrap: wrap;
|
text-wrap: wrap;
|
||||||
|
transition:
|
||||||
|
background-color 0.3s var(--ease-in-out),
|
||||||
|
color 0.3s var(--ease-in-out);
|
||||||
|
|
||||||
& .copy-button {
|
& .copy-button {
|
||||||
all: unset;
|
all: unset;
|
||||||
|
|
@ -41,18 +44,29 @@ pre {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
color: hsl(var(--blue) 100% 69%);
|
color: hsla(var(--blue) 100 69 / 0.33);
|
||||||
background-color: hsl(var(--blue) 85% 35% / 0.1);
|
background-color: hsla(var(--blue) 85 35 / 0.01);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: color 0.25s;
|
transition:
|
||||||
|
background-color 0.3s var(--ease-in-out),
|
||||||
|
color 0.3s var(--ease-in-out);
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: hsl(var(--blue) 100% 75%);
|
color: hsla(var(--blue) 100 75 / 0.75);
|
||||||
|
background-color: hsla(var(--blue) 85 35 / 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.copied {
|
&.copied {
|
||||||
animation: pulseGreen 0.5s cubic-bezier(0, 1, 0.6, 1);
|
animation: var(--animate-bounce);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.shiki {
|
||||||
|
box-shadow: var(--shadow-xl);
|
||||||
|
|
||||||
|
&:hover .copy-button {
|
||||||
|
background-color: hsla(var(--blue) 85 35 / 0.07);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,17 @@
|
||||||
transition: none !important;
|
transition: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.theme-toggle {
|
||||||
|
height: 24px;
|
||||||
|
font-size: 1.614rem;
|
||||||
|
color: hsla(var(--signal-color) / 0.7);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
color: hsla(var(--signal-color) / 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* color styling */
|
/* color styling */
|
||||||
.header {
|
.header {
|
||||||
background-color: hsl(var(--bg-400));
|
background-color: hsl(var(--bg-400));
|
||||||
|
|
@ -49,6 +60,14 @@ html.dark {
|
||||||
background-color: hsl(var(--secondary-900));
|
background-color: hsl(var(--secondary-900));
|
||||||
color: hsl(var(--secondary-500));
|
color: hsl(var(--secondary-500));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& .theme-toggle {
|
||||||
|
color: hsla(var(--func-color) / 0.7);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: hsla(var(--func-color) / 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* layout and positioning */
|
/* layout and positioning */
|
||||||
|
|
@ -56,10 +75,12 @@ html.dark {
|
||||||
width: 75%;
|
width: 75%;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
margin-block: 0.618rem;
|
margin-block: 0.618rem;
|
||||||
background: linear-gradient(to right,
|
background: linear-gradient(
|
||||||
transparent,
|
to right,
|
||||||
hsl(var(--blue) 100% 59%),
|
transparent,
|
||||||
transparent);
|
hsl(var(--blue) 100% 59%),
|
||||||
|
transparent
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.unset {
|
.unset {
|
||||||
|
|
@ -130,15 +151,6 @@ body.overflow-toc {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-toggle {
|
|
||||||
height: 24px;
|
|
||||||
font-size: 1.614rem;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
@ -146,7 +158,6 @@ footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 1rem 2rem;
|
padding: 1rem 2rem;
|
||||||
overflow: hidden;
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
background: hsl(var(--footer-bkg));
|
background: hsl(var(--footer-bkg));
|
||||||
|
|
||||||
|
|
@ -154,13 +165,38 @@ footer {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: -1rem;
|
left: 0;
|
||||||
|
right: 54%;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
width: calc(100% + 1rem);
|
width: calc(48%);
|
||||||
background: linear-gradient(90deg,
|
background: linear-gradient(
|
||||||
transparent 0%,
|
90deg,
|
||||||
hsl(var(--footer-bkg-border)) 50%,
|
transparent 0%,
|
||||||
transparent 100%);
|
hsl(var(--footer-bkg-border)) 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 54%;
|
||||||
|
height: 1px;
|
||||||
|
width: calc(48% - 1rem);
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
hsl(var(--footer-bkg-border)) 0%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
& .theme-toggle {
|
||||||
|
position: absolute;
|
||||||
|
top: -12px;
|
||||||
|
left: 50%;
|
||||||
|
width: max-content;
|
||||||
|
height: max-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
& a {
|
& a {
|
||||||
|
|
@ -199,12 +235,12 @@ footer {
|
||||||
gap: 0.2rem;
|
gap: 0.2rem;
|
||||||
color: hsl(var(--text-dark));
|
color: hsl(var(--text-dark));
|
||||||
|
|
||||||
&>p {
|
& > p {
|
||||||
margin-bottom: 0.2rem;
|
margin-bottom: 0.2rem;
|
||||||
color: hsl(0deg 0% 40%);
|
color: hsl(0deg 0% 40%);
|
||||||
}
|
}
|
||||||
|
|
||||||
&>a {
|
& > a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -218,7 +254,6 @@ footer {
|
||||||
gap: 0.373rem;
|
gap: 0.373rem;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
font-size: 2.5rem;
|
font-size: 2.5rem;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
& .changelog {
|
& .changelog {
|
||||||
|
|
@ -235,7 +270,7 @@ footer {
|
||||||
footer {
|
footer {
|
||||||
padding-inline: 0.75rem;
|
padding-inline: 0.75rem;
|
||||||
|
|
||||||
& .credits>a {
|
& .credits > a {
|
||||||
padding: 0.2rem 0;
|
padding: 0.2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue