Skip to content

Instantly share code, notes, and snippets.

@Spurlos
Created September 5, 2023 00:51
Show Gist options
  • Save Spurlos/f6339c3009c89bbbf8091a721973c28d to your computer and use it in GitHub Desktop.
Save Spurlos/f6339c3009c89bbbf8091a721973c28d to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.marquee-container {
width: 100%;
overflow: hidden;
position: relative;
white-space: nowrap;
}
.marquee-content {
display: inline-block;
white-space: nowrap;
animation: marquee linear infinite; /* Use linear timing function */
}
@keyframes marquee {
0% {
transform: translateX(0%);
}
100% {
transform: translateX(-100%);
}
}
</style>
</head>
<body>
<div class="marquee-container" id="marquee-container">
</div>
<script>
const container = document.getElementById("marquee-container");
const text = "Lorem ipsum dolor; ";
const textWidth = getTextWidth(text); // Get the width of the text
// Calculate the animation duration coefficient based on the desired duration (e.g., 4 seconds) and a reference text width (e.g., 100px)
const desiredDuration = 4; // Desired animation duration in seconds
const referenceTextWidth = 100; // Reference text width in pixels
const animationDurationCoefficient = desiredDuration / referenceTextWidth;
// Calculate the animation duration based on the actual text width
const animationDuration = animationDurationCoefficient * textWidth;
function createMarquee() {
const marquee = document.createElement("div");
marquee.className = "marquee-content";
marquee.textContent = text;
marquee.style.animationDuration = animationDuration + "s";
container.appendChild(marquee);
}
// Helper function to get the width of the text
function getTextWidth(text) {
const span = document.createElement("span");
span.style.visibility = "hidden";
span.style.whiteSpace = "nowrap";
span.textContent = text;
container.appendChild(span);
const width = span.offsetWidth;
container.removeChild(span);
return width;
}
// Function to continuously add new marquee blocks
function addMarquees() {
const marqueeElements = container.querySelectorAll(".marquee-content");
let totalWidth = 0;
// Calculate the total width of existing marquee blocks
marqueeElements.forEach((marquee) => {
totalWidth += marquee.offsetWidth;
});
// Calculate the number of blocks that can fit in the viewport
const blocksPerViewport = Math.floor(window.innerWidth / textWidth);
// Calculate the number of blocks needed to fill the viewport
const blocksToAdd = blocksPerViewport - Math.ceil(totalWidth / textWidth) + 2; // Add two more blocks
// Add new marquee blocks to fill the viewport
for (let i = 0; i < blocksToAdd; i++) {
createMarquee();
}
removeMarqueeIfNeeded();
}
function removeMarqueeIfNeeded() {
const marqueeElements = container.querySelectorAll(".marquee-content");
for (const marquee of marqueeElements) {
const rect = marquee.getBoundingClientRect();
if (rect.right <= 0) {
container.removeChild(marquee);
}
}
}
// Start by adding marquee blocks based on the available space
addMarquees();
// Use Intersection Observer to detect when new marquee blocks should appear
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
addMarquees();
}
});
});
// Observe the container
observer.observe(container);
// Listen for viewport changes and recalculate
window.addEventListener("resize", () => {
// Clear existing marquee blocks
const marqueeElements = container.querySelectorAll(".marquee-content");
marqueeElements.forEach((marquee) => {
container.removeChild(marquee);
});
// Re-add marquee blocks based on the new viewport size
addMarquees();
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment